mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2025-06-03 00:00:20 +00:00
Cleaned up collections:
ArrayList, MessageQueue, Queue, PubSub, BipBuffer ObjectPool and BufferPool
This commit is contained in:
parent
96bb569674
commit
6e3c00725a
@ -42,7 +42,6 @@ static void dvcman_wtslistener_free(DVCMAN_LISTENER* listener)
|
|||||||
{
|
{
|
||||||
if (listener)
|
if (listener)
|
||||||
free(listener->channel_name);
|
free(listener->channel_name);
|
||||||
|
|
||||||
free(listener);
|
free(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +393,6 @@ static void dvcman_clear(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pCha
|
|||||||
ArrayList_Clear(dvcman->plugin_names);
|
ArrayList_Clear(dvcman->plugin_names);
|
||||||
ArrayList_Clear(dvcman->listeners);
|
ArrayList_Clear(dvcman->listeners);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr)
|
static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr)
|
||||||
{
|
{
|
||||||
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
|
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
|
||||||
@ -1436,7 +1434,7 @@ static void drdynvc_queue_object_free(void* obj)
|
|||||||
static UINT drdynvc_virtual_channel_event_initialized(drdynvcPlugin* drdynvc, LPVOID pData,
|
static UINT drdynvc_virtual_channel_event_initialized(drdynvcPlugin* drdynvc, LPVOID pData,
|
||||||
UINT32 dataLength)
|
UINT32 dataLength)
|
||||||
{
|
{
|
||||||
UINT error = CHANNEL_RC_OK;
|
wObject* obj;
|
||||||
WINPR_UNUSED(pData);
|
WINPR_UNUSED(pData);
|
||||||
WINPR_UNUSED(dataLength);
|
WINPR_UNUSED(dataLength);
|
||||||
|
|
||||||
@ -1447,17 +1445,18 @@ static UINT drdynvc_virtual_channel_event_initialized(drdynvcPlugin* drdynvc, LP
|
|||||||
|
|
||||||
if (!drdynvc->queue)
|
if (!drdynvc->queue)
|
||||||
{
|
{
|
||||||
error = CHANNEL_RC_NO_MEMORY;
|
|
||||||
WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_New failed!");
|
WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_New failed!");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
drdynvc->queue->object.fnObjectFree = drdynvc_queue_object_free;
|
obj = MessageQueue_Object(drdynvc->queue);
|
||||||
|
if (!obj)
|
||||||
|
goto error;
|
||||||
|
obj->fnObjectFree = drdynvc_queue_object_free;
|
||||||
drdynvc->channel_mgr = dvcman_new(drdynvc);
|
drdynvc->channel_mgr = dvcman_new(drdynvc);
|
||||||
|
|
||||||
if (!drdynvc->channel_mgr)
|
if (!drdynvc->channel_mgr)
|
||||||
{
|
{
|
||||||
error = CHANNEL_RC_NO_MEMORY;
|
|
||||||
WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_new failed!");
|
WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_new failed!");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -1562,7 +1561,6 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
|
|||||||
|
|
||||||
CloseHandle(drdynvc->thread);
|
CloseHandle(drdynvc->thread);
|
||||||
drdynvc->thread = NULL;
|
drdynvc->thread = NULL;
|
||||||
|
|
||||||
status = drdynvc->channelEntryPoints.pVirtualChannelCloseEx(drdynvc->InitHandle,
|
status = drdynvc->channelEntryPoints.pVirtualChannelCloseEx(drdynvc->InitHandle,
|
||||||
drdynvc->OpenHandle);
|
drdynvc->OpenHandle);
|
||||||
|
|
||||||
@ -1603,7 +1601,6 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
|
|||||||
dvcman_free(drdynvc, drdynvc->channel_mgr);
|
dvcman_free(drdynvc, drdynvc->channel_mgr);
|
||||||
drdynvc->channel_mgr = NULL;
|
drdynvc->channel_mgr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
drdynvc->InitHandle = 0;
|
drdynvc->InitHandle = 0;
|
||||||
free(drdynvc->context);
|
free(drdynvc->context);
|
||||||
free(drdynvc);
|
free(drdynvc);
|
||||||
|
@ -1661,6 +1661,7 @@ static void queue_free(void* obj)
|
|||||||
static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pData,
|
static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pData,
|
||||||
UINT32 dataLength)
|
UINT32 dataLength)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
UINT32 status;
|
UINT32 status;
|
||||||
status = rdpdr->channelEntryPoints.pVirtualChannelOpenEx(rdpdr->InitHandle, &rdpdr->OpenHandle,
|
status = rdpdr->channelEntryPoints.pVirtualChannelOpenEx(rdpdr->InitHandle, &rdpdr->OpenHandle,
|
||||||
rdpdr->channelDef.name,
|
rdpdr->channelDef.name,
|
||||||
@ -1681,7 +1682,10 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pDa
|
|||||||
return CHANNEL_RC_NO_MEMORY;
|
return CHANNEL_RC_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdpdr->queue->object.fnObjectFree = queue_free;
|
obj = MessageQueue_Object(rdpdr->queue);
|
||||||
|
if (!obj)
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
obj->fnObjectFree = queue_free;
|
||||||
|
|
||||||
if (!(rdpdr->thread =
|
if (!(rdpdr->thread =
|
||||||
CreateThread(NULL, 0, rdpdr_virtual_channel_client_thread, (void*)rdpdr, 0, NULL)))
|
CreateThread(NULL, 0, rdpdr_virtual_channel_client_thread, (void*)rdpdr, 0, NULL)))
|
||||||
|
@ -332,13 +332,14 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
|
|||||||
// puts a buffer of size samples to the device
|
// puts a buffer of size samples to the device
|
||||||
int android_AudioOut(OPENSL_STREAM* p, const short* buffer, int size)
|
int android_AudioOut(OPENSL_STREAM* p, const short* buffer, int size)
|
||||||
{
|
{
|
||||||
|
HANDLE ev;
|
||||||
assert(p);
|
assert(p);
|
||||||
assert(buffer);
|
assert(buffer);
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
|
|
||||||
|
ev = Queue_Event(p->queue);
|
||||||
/* Assure, that the queue is not full. */
|
/* Assure, that the queue is not full. */
|
||||||
if (p->queuesize <= Queue_Count(p->queue) &&
|
if (p->queuesize <= Queue_Count(p->queue) && WaitForSingleObject(ev, INFINITE) == WAIT_FAILED)
|
||||||
WaitForSingleObject(p->queue->event, INFINITE) == WAIT_FAILED)
|
|
||||||
{
|
{
|
||||||
DEBUG_SND("WaitForSingleObject failed!");
|
DEBUG_SND("WaitForSingleObject failed!");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -101,9 +101,9 @@ static BOOL smartcard_ndr_pointer_read_(wStream* s, UINT32* index, UINT32* ptr,
|
|||||||
static LONG smartcard_ndr_read(wStream* s, BYTE** data, size_t min, size_t elementSize,
|
static LONG smartcard_ndr_read(wStream* s, BYTE** data, size_t min, size_t elementSize,
|
||||||
ndr_ptr_t type)
|
ndr_ptr_t type)
|
||||||
{
|
{
|
||||||
size_t len, offset, len2;
|
size_t len = 0, offset, len2;
|
||||||
void* r;
|
void* r;
|
||||||
size_t required;
|
size_t required = 0;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -346,6 +346,7 @@ finally:
|
|||||||
TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid,
|
TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid,
|
||||||
IWTSVirtualChannelCallback* pChannelCallback)
|
IWTSVirtualChannelCallback* pChannelCallback)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
TSMF_PRESENTATION* presentation;
|
TSMF_PRESENTATION* presentation;
|
||||||
|
|
||||||
if (!guid || !pChannelCallback)
|
if (!guid || !pChannelCallback)
|
||||||
@ -367,7 +368,10 @@ TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid,
|
|||||||
if (!(presentation->stream_list = ArrayList_New(TRUE)))
|
if (!(presentation->stream_list = ArrayList_New(TRUE)))
|
||||||
goto error_stream_list;
|
goto error_stream_list;
|
||||||
|
|
||||||
ArrayList_Object(presentation->stream_list)->fnObjectFree = _tsmf_stream_free;
|
obj = ArrayList_Object(presentation->stream_list);
|
||||||
|
if (!obj)
|
||||||
|
goto error_add;
|
||||||
|
obj->fnObjectFree = _tsmf_stream_free;
|
||||||
|
|
||||||
if (ArrayList_Add(presentation_list, presentation) < 0)
|
if (ArrayList_Add(presentation_list, presentation) < 0)
|
||||||
goto error_add;
|
goto error_add;
|
||||||
@ -1206,6 +1210,7 @@ void tsmf_presentation_free(TSMF_PRESENTATION* presentation)
|
|||||||
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id,
|
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id,
|
||||||
rdpContext* rdpcontext)
|
rdpContext* rdpcontext)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
TSMF_STREAM* stream;
|
TSMF_STREAM* stream;
|
||||||
stream = tsmf_stream_find_by_id(presentation, stream_id);
|
stream = tsmf_stream_find_by_id(presentation, stream_id);
|
||||||
|
|
||||||
@ -1247,13 +1252,21 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id,
|
|||||||
if (!stream->sample_list)
|
if (!stream->sample_list)
|
||||||
goto error_sample_list;
|
goto error_sample_list;
|
||||||
|
|
||||||
stream->sample_list->object.fnObjectFree = tsmf_sample_free;
|
obj = Queue_Object(stream->sample_list);
|
||||||
|
if (!obj)
|
||||||
|
goto error_sample_ack_list;
|
||||||
|
obj->fnObjectFree = tsmf_sample_free;
|
||||||
|
|
||||||
stream->sample_ack_list = Queue_New(TRUE, -1, -1);
|
stream->sample_ack_list = Queue_New(TRUE, -1, -1);
|
||||||
|
|
||||||
if (!stream->sample_ack_list)
|
if (!stream->sample_ack_list)
|
||||||
goto error_sample_ack_list;
|
goto error_sample_ack_list;
|
||||||
|
|
||||||
stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free;
|
obj = Queue_Object(stream->sample_ack_list);
|
||||||
|
if (!obj)
|
||||||
|
goto error_play_thread;
|
||||||
|
obj->fnObjectFree = tsmf_sample_free;
|
||||||
|
|
||||||
stream->play_thread =
|
stream->play_thread =
|
||||||
CreateThread(NULL, 0, tsmf_stream_playback_func, stream, CREATE_SUSPENDED, NULL);
|
CreateThread(NULL, 0, tsmf_stream_playback_func, stream, CREATE_SUSPENDED, NULL);
|
||||||
|
|
||||||
@ -1529,6 +1542,7 @@ static void tsmf_signal_handler(int s)
|
|||||||
|
|
||||||
BOOL tsmf_media_init(void)
|
BOOL tsmf_media_init(void)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
struct sigaction sigtrap;
|
struct sigaction sigtrap;
|
||||||
sigtrap.sa_handler = tsmf_signal_handler;
|
sigtrap.sa_handler = tsmf_signal_handler;
|
||||||
@ -1545,7 +1559,10 @@ BOOL tsmf_media_init(void)
|
|||||||
if (!presentation_list)
|
if (!presentation_list)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
ArrayList_Object(presentation_list)->fnObjectFree = _tsmf_presentation_free;
|
obj = ArrayList_Object(presentation_list);
|
||||||
|
if (!obj)
|
||||||
|
return FALSE;
|
||||||
|
obj->fnObjectFree = _tsmf_presentation_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -903,6 +903,7 @@ static DWORD poll_thread(LPVOID lpThreadParameter)
|
|||||||
#endif
|
#endif
|
||||||
UINT freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)
|
UINT freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
UINT rc;
|
UINT rc;
|
||||||
UINT status;
|
UINT status;
|
||||||
UDEVMAN* udevman;
|
UDEVMAN* udevman;
|
||||||
@ -915,8 +916,11 @@ UINT freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS
|
|||||||
udevman->hotplug_vid_pids = ArrayList_New(TRUE);
|
udevman->hotplug_vid_pids = ArrayList_New(TRUE);
|
||||||
if (!udevman->hotplug_vid_pids)
|
if (!udevman->hotplug_vid_pids)
|
||||||
goto fail;
|
goto fail;
|
||||||
ArrayList_Object(udevman->hotplug_vid_pids)->fnObjectFree = free;
|
obj = ArrayList_Object(udevman->hotplug_vid_pids);
|
||||||
ArrayList_Object(udevman->hotplug_vid_pids)->fnObjectEquals = udevman_vid_pid_pair_equals;
|
if (!obj)
|
||||||
|
goto fail;
|
||||||
|
obj->fnObjectFree = free;
|
||||||
|
obj->fnObjectEquals = udevman_vid_pid_pair_equals;
|
||||||
|
|
||||||
udevman->next_device_id = BASE_USBDEVICE_NUM;
|
udevman->next_device_id = BASE_USBDEVICE_NUM;
|
||||||
udevman->iface.plugin = pEntryPoints->plugin;
|
udevman->iface.plugin = pEntryPoints->plugin;
|
||||||
|
@ -167,6 +167,7 @@ static const char* x11_event_string(int event)
|
|||||||
|
|
||||||
BOOL xf_event_action_script_init(xfContext* xfc)
|
BOOL xf_event_action_script_init(xfContext* xfc)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
char* xevent;
|
char* xevent;
|
||||||
FILE* actionScript;
|
FILE* actionScript;
|
||||||
char buffer[1024] = { 0 };
|
char buffer[1024] = { 0 };
|
||||||
@ -176,7 +177,10 @@ BOOL xf_event_action_script_init(xfContext* xfc)
|
|||||||
if (!xfc->xevents)
|
if (!xfc->xevents)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
ArrayList_Object(xfc->xevents)->fnObjectFree = free;
|
obj = ArrayList_Object(xfc->xevents);
|
||||||
|
if (!obj)
|
||||||
|
return FALSE;
|
||||||
|
obj->fnObjectFree = free;
|
||||||
sprintf_s(command, sizeof(command), "%s xevent", xfc->context.settings->ActionScript);
|
sprintf_s(command, sizeof(command), "%s xevent", xfc->context.settings->ActionScript);
|
||||||
actionScript = popen(command, "r");
|
actionScript = popen(command, "r");
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ static BOOL ungrabKeyboardWithRightCtrl = TRUE;
|
|||||||
|
|
||||||
static BOOL xf_keyboard_action_script_init(xfContext* xfc)
|
static BOOL xf_keyboard_action_script_init(xfContext* xfc)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
FILE* keyScript;
|
FILE* keyScript;
|
||||||
char* keyCombination;
|
char* keyCombination;
|
||||||
char buffer[1024] = { 0 };
|
char buffer[1024] = { 0 };
|
||||||
@ -62,7 +63,10 @@ static BOOL xf_keyboard_action_script_init(xfContext* xfc)
|
|||||||
if (!xfc->keyCombinations)
|
if (!xfc->keyCombinations)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
ArrayList_Object(xfc->keyCombinations)->fnObjectFree = free;
|
obj = ArrayList_Object(xfc->keyCombinations);
|
||||||
|
if (!obj)
|
||||||
|
return FALSE;
|
||||||
|
obj->fnObjectFree = free;
|
||||||
sprintf_s(command, sizeof(command), "%s key", xfc->context.settings->ActionScript);
|
sprintf_s(command, sizeof(command), "%s key", xfc->context.settings->ActionScript);
|
||||||
keyScript = popen(command, "r");
|
keyScript = popen(command, "r");
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ static void rfx_tile_init(void* obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* rfx_decoder_tile_new(void* val)
|
static void* rfx_decoder_tile_new(const void* val)
|
||||||
{
|
{
|
||||||
RFX_TILE* tile = NULL;
|
RFX_TILE* tile = NULL;
|
||||||
WINPR_UNUSED(val);
|
WINPR_UNUSED(val);
|
||||||
@ -184,7 +184,7 @@ static void rfx_decoder_tile_free(void* obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* rfx_encoder_tile_new(void* val)
|
static void* rfx_encoder_tile_new(const void* val)
|
||||||
{
|
{
|
||||||
WINPR_UNUSED(val);
|
WINPR_UNUSED(val);
|
||||||
return calloc(1, sizeof(RFX_TILE));
|
return calloc(1, sizeof(RFX_TILE));
|
||||||
|
@ -137,6 +137,7 @@ static BOOL CALLBACK init_channel_handles_table(PINIT_ONCE once, PVOID param, PV
|
|||||||
|
|
||||||
rdpChannels* freerdp_channels_new(freerdp* instance)
|
rdpChannels* freerdp_channels_new(freerdp* instance)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
rdpChannels* channels;
|
rdpChannels* channels;
|
||||||
channels = (rdpChannels*)calloc(1, sizeof(rdpChannels));
|
channels = (rdpChannels*)calloc(1, sizeof(rdpChannels));
|
||||||
|
|
||||||
@ -147,7 +148,6 @@ rdpChannels* freerdp_channels_new(freerdp* instance)
|
|||||||
|
|
||||||
if (!g_ChannelHandles)
|
if (!g_ChannelHandles)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!InitializeCriticalSectionAndSpinCount(&channels->channelsLock, 4000))
|
if (!InitializeCriticalSectionAndSpinCount(&channels->channelsLock, 4000))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -157,7 +157,11 @@ rdpChannels* freerdp_channels_new(freerdp* instance)
|
|||||||
if (!channels->queue)
|
if (!channels->queue)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
channels->queue->object.fnObjectFree = channel_queue_free;
|
obj = MessageQueue_Object(channels->queue);
|
||||||
|
if (!obj)
|
||||||
|
goto error;
|
||||||
|
obj->fnObjectFree = channel_queue_free;
|
||||||
|
|
||||||
return channels;
|
return channels;
|
||||||
error:
|
error:
|
||||||
freerdp_channels_free(channels);
|
freerdp_channels_free(channels);
|
||||||
@ -584,7 +588,6 @@ static BOOL freerdp_channels_process_message(freerdp* instance, wMessage* messag
|
|||||||
freerdp_channels_process_message_free(message, CHANNEL_EVENT_WRITE_CANCELLED);
|
freerdp_channels_process_message_free(message, CHANNEL_EVENT_WRITE_CANCELLED);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
channel =
|
channel =
|
||||||
freerdp_channels_find_channel_by_name(instance->context->rdp, pChannelOpenData->name);
|
freerdp_channels_find_channel_by_name(instance->context->rdp, pChannelOpenData->name);
|
||||||
|
|
||||||
@ -729,9 +732,7 @@ void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
|
|||||||
int index;
|
int index;
|
||||||
CHANNEL_OPEN_DATA* pChannelOpenData;
|
CHANNEL_OPEN_DATA* pChannelOpenData;
|
||||||
CHANNEL_CLIENT_DATA* pChannelClientData;
|
CHANNEL_CLIENT_DATA* pChannelClientData;
|
||||||
|
|
||||||
MessageQueue_PostQuit(channels->queue, 0);
|
MessageQueue_PostQuit(channels->queue, 0);
|
||||||
|
|
||||||
freerdp_channels_check_fds(channels, instance);
|
freerdp_channels_check_fds(channels, instance);
|
||||||
|
|
||||||
/* tell all libraries we are shutting down */
|
/* tell all libraries we are shutting down */
|
||||||
@ -1019,6 +1020,7 @@ static UINT VCAPITYPE FreeRDP_VirtualChannelCloseEx(LPVOID pInitHandle, DWORD op
|
|||||||
return CHANNEL_RC_BAD_INIT_HANDLE;
|
return CHANNEL_RC_BAD_INIT_HANDLE;
|
||||||
|
|
||||||
pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
|
pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
|
||||||
|
|
||||||
if (!pChannelOpenData)
|
if (!pChannelOpenData)
|
||||||
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
|
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
|
||||||
|
|
||||||
|
@ -1041,6 +1041,7 @@ static BOOL rpc_client_resolve_gateway(rdpSettings* settings, char** host, UINT1
|
|||||||
|
|
||||||
RpcClient* rpc_client_new(rdpContext* context, UINT32 max_recv_frag)
|
RpcClient* rpc_client_new(rdpContext* context, UINT32 max_recv_frag)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
RpcClient* client = (RpcClient*)calloc(1, sizeof(RpcClient));
|
RpcClient* client = (RpcClient*)calloc(1, sizeof(RpcClient));
|
||||||
|
|
||||||
if (!client)
|
if (!client)
|
||||||
@ -1081,7 +1082,11 @@ RpcClient* rpc_client_new(rdpContext* context, UINT32 max_recv_frag)
|
|||||||
if (!client->ClientCallList)
|
if (!client->ClientCallList)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ArrayList_Object(client->ClientCallList)->fnObjectFree = rpc_array_client_call_free;
|
obj = ArrayList_Object(client->ClientCallList);
|
||||||
|
if (!obj)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
obj->fnObjectFree = rpc_array_client_call_free;
|
||||||
return client;
|
return client;
|
||||||
fail:
|
fail:
|
||||||
rpc_client_free(client);
|
rpc_client_free(client);
|
||||||
|
@ -63,6 +63,65 @@ static const char* pf_modules_get_hook_type_string(PF_HOOK_TYPE result)
|
|||||||
return "HOOK_UNKNOWN";
|
return "HOOK_UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL pf_modules_proxy_ArrayList_ForEachFkt(void* data, size_t index, va_list ap)
|
||||||
|
{
|
||||||
|
proxyPlugin* plugin = (proxyPlugin*)data;
|
||||||
|
PF_HOOK_TYPE type;
|
||||||
|
proxyData* pdata;
|
||||||
|
BOOL ok = FALSE;
|
||||||
|
|
||||||
|
type = va_arg(ap, PF_HOOK_TYPE);
|
||||||
|
pdata = va_arg(ap, proxyData*);
|
||||||
|
|
||||||
|
WLog_VRB(TAG, "running hook %s.%s", plugin->name, pf_modules_get_hook_type_string(type));
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case HOOK_TYPE_CLIENT_PRE_CONNECT:
|
||||||
|
IFCALLRET(plugin->ClientPreConnect, ok, pdata);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HOOK_TYPE_CLIENT_POST_CONNECT:
|
||||||
|
IFCALLRET(plugin->ClientPostConnect, ok, pdata);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HOOK_TYPE_CLIENT_LOGIN_FAILURE:
|
||||||
|
IFCALLRET(plugin->ClientLoginFailure, ok, pdata);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HOOK_TYPE_CLIENT_END_PAINT:
|
||||||
|
IFCALLRET(plugin->ClientEndPaint, ok, pdata);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HOOK_TYPE_SERVER_POST_CONNECT:
|
||||||
|
IFCALLRET(plugin->ServerPostConnect, ok, pdata);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HOOK_TYPE_SERVER_CHANNELS_INIT:
|
||||||
|
IFCALLRET(plugin->ServerChannelsInit, ok, pdata);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HOOK_TYPE_SERVER_CHANNELS_FREE:
|
||||||
|
IFCALLRET(plugin->ServerChannelsFree, ok, pdata);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HOOK_TYPE_SERVER_SESSION_END:
|
||||||
|
IFCALLRET(plugin->ServerSessionEnd, ok, pdata);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
WLog_ERR(TAG, "invalid hook called");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
WLog_INFO(TAG, "plugin %s, hook %s failed!", plugin->name,
|
||||||
|
pf_modules_get_hook_type_string(type));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* runs all hooks of type `type`.
|
* runs all hooks of type `type`.
|
||||||
*
|
*
|
||||||
@ -71,61 +130,56 @@ static const char* pf_modules_get_hook_type_string(PF_HOOK_TYPE result)
|
|||||||
*/
|
*/
|
||||||
BOOL pf_modules_run_hook(PF_HOOK_TYPE type, proxyData* pdata)
|
BOOL pf_modules_run_hook(PF_HOOK_TYPE type, proxyData* pdata)
|
||||||
{
|
{
|
||||||
BOOL ok = TRUE;
|
return ArrayList_ForEach(plugins_list, pf_modules_proxy_ArrayList_ForEachFkt, type, pdata);
|
||||||
int index;
|
}
|
||||||
proxyPlugin* plugin;
|
|
||||||
|
|
||||||
ArrayList_ForEach(plugins_list, proxyPlugin*, index, plugin)
|
static BOOL pf_modules_ArrayList_ForEachFkt(void* data, size_t index, va_list ap)
|
||||||
|
{
|
||||||
|
proxyPlugin* plugin = (proxyPlugin*)data;
|
||||||
|
PF_HOOK_TYPE type;
|
||||||
|
proxyData* pdata;
|
||||||
|
void* param;
|
||||||
|
BOOL result = FALSE;
|
||||||
|
|
||||||
|
type = va_arg(ap, PF_HOOK_TYPE);
|
||||||
|
pdata = va_arg(ap, proxyData*);
|
||||||
|
param = va_arg(ap, void*);
|
||||||
|
|
||||||
|
WLog_VRB(TAG, "[%s]: running filter: %s", __FUNCTION__, plugin->name);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
{
|
{
|
||||||
WLog_VRB(TAG, "running hook %s.%s", plugin->name, pf_modules_get_hook_type_string(type));
|
case FILTER_TYPE_KEYBOARD:
|
||||||
|
IFCALLRET(plugin->KeyboardEvent, result, pdata, param);
|
||||||
|
break;
|
||||||
|
|
||||||
switch (type)
|
case FILTER_TYPE_MOUSE:
|
||||||
{
|
IFCALLRET(plugin->MouseEvent, result, pdata, param);
|
||||||
case HOOK_TYPE_CLIENT_PRE_CONNECT:
|
break;
|
||||||
IFCALLRET(plugin->ClientPreConnect, ok, pdata);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HOOK_TYPE_CLIENT_POST_CONNECT:
|
case FILTER_TYPE_CLIENT_PASSTHROUGH_CHANNEL_DATA:
|
||||||
IFCALLRET(plugin->ClientPostConnect, ok, pdata);
|
IFCALLRET(plugin->ClientChannelData, result, pdata, param);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HOOK_TYPE_CLIENT_LOGIN_FAILURE:
|
case FILTER_TYPE_SERVER_PASSTHROUGH_CHANNEL_DATA:
|
||||||
IFCALLRET(plugin->ClientLoginFailure, ok, pdata);
|
IFCALLRET(plugin->ServerChannelData, result, pdata, param);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HOOK_TYPE_CLIENT_END_PAINT:
|
case FILTER_TYPE_SERVER_FETCH_TARGET_ADDR:
|
||||||
IFCALLRET(plugin->ClientEndPaint, ok, pdata);
|
IFCALLRET(plugin->ServerFetchTargetAddr, result, pdata, param);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HOOK_TYPE_SERVER_POST_CONNECT:
|
default:
|
||||||
IFCALLRET(plugin->ServerPostConnect, ok, pdata);
|
WLog_ERR(TAG, "invalid filter called");
|
||||||
break;
|
|
||||||
|
|
||||||
case HOOK_TYPE_SERVER_CHANNELS_INIT:
|
|
||||||
IFCALLRET(plugin->ServerChannelsInit, ok, pdata);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HOOK_TYPE_SERVER_CHANNELS_FREE:
|
|
||||||
IFCALLRET(plugin->ServerChannelsFree, ok, pdata);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HOOK_TYPE_SERVER_SESSION_END:
|
|
||||||
IFCALLRET(plugin->ServerSessionEnd, ok, pdata);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
WLog_ERR(TAG, "invalid hook called");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
WLog_INFO(TAG, "plugin %s, hook %s failed!", plugin->name,
|
|
||||||
pf_modules_get_hook_type_string(type));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
if (!result)
|
||||||
|
{
|
||||||
|
/* current filter return FALSE, no need to run other filters. */
|
||||||
|
WLog_DBG(TAG, "plugin %s, filter type [%s] returned FALSE", plugin->name,
|
||||||
|
pf_modules_get_filter_type_string(type));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -136,51 +190,8 @@ BOOL pf_modules_run_hook(PF_HOOK_TYPE type, proxyData* pdata)
|
|||||||
*/
|
*/
|
||||||
BOOL pf_modules_run_filter(PF_FILTER_TYPE type, proxyData* pdata, void* param)
|
BOOL pf_modules_run_filter(PF_FILTER_TYPE type, proxyData* pdata, void* param)
|
||||||
{
|
{
|
||||||
BOOL result = TRUE;
|
|
||||||
int index;
|
|
||||||
proxyPlugin* plugin;
|
|
||||||
|
|
||||||
ArrayList_ForEach(plugins_list, proxyPlugin*, index, plugin)
|
return ArrayList_ForEach(plugins_list, pf_modules_ArrayList_ForEachFkt, type, pdata, param);
|
||||||
{
|
|
||||||
WLog_VRB(TAG, "[%s]: running filter: %s", __FUNCTION__, plugin->name);
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case FILTER_TYPE_KEYBOARD:
|
|
||||||
IFCALLRET(plugin->KeyboardEvent, result, pdata, param);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FILTER_TYPE_MOUSE:
|
|
||||||
IFCALLRET(plugin->MouseEvent, result, pdata, param);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FILTER_TYPE_CLIENT_PASSTHROUGH_CHANNEL_DATA:
|
|
||||||
IFCALLRET(plugin->ClientChannelData, result, pdata, param);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FILTER_TYPE_SERVER_PASSTHROUGH_CHANNEL_DATA:
|
|
||||||
IFCALLRET(plugin->ServerChannelData, result, pdata, param);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FILTER_TYPE_SERVER_FETCH_TARGET_ADDR:
|
|
||||||
IFCALLRET(plugin->ServerFetchTargetAddr, result, pdata, param);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
WLog_ERR(TAG, "invalid filter called");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
/* current filter return FALSE, no need to run other filters. */
|
|
||||||
WLog_DBG(TAG, "plugin %s, filter type [%s] returned FALSE", plugin->name,
|
|
||||||
pf_modules_get_filter_type_string(type));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* all filters returned TRUE */
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -238,23 +249,30 @@ static void pf_modules_abort_connect(proxyData* pdata)
|
|||||||
proxy_data_abort_connect(pdata);
|
proxy_data_abort_connect(pdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL pf_modules_register_ArrayList_ForEachFkt(void* data, size_t index, va_list ap)
|
||||||
|
{
|
||||||
|
proxyPlugin* plugin = (proxyPlugin*)data;
|
||||||
|
proxyPlugin* plugin_to_register = va_arg(ap, proxyPlugin*);
|
||||||
|
|
||||||
|
WINPR_UNUSED(index);
|
||||||
|
|
||||||
|
if (strcmp(plugin->name, plugin_to_register->name) == 0)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "can not register plugin '%s', it is already registered!", plugin->name);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL pf_modules_register_plugin(proxyPlugin* plugin_to_register)
|
static BOOL pf_modules_register_plugin(proxyPlugin* plugin_to_register)
|
||||||
{
|
{
|
||||||
int index;
|
|
||||||
proxyPlugin* plugin;
|
|
||||||
|
|
||||||
if (!plugin_to_register)
|
if (!plugin_to_register)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* make sure there's no other loaded plugin with the same name of `plugin_to_register`. */
|
/* make sure there's no other loaded plugin with the same name of `plugin_to_register`. */
|
||||||
ArrayList_ForEach(plugins_list, proxyPlugin*, index, plugin)
|
if (!ArrayList_ForEach(plugins_list, pf_modules_register_ArrayList_ForEachFkt,
|
||||||
{
|
plugin_to_register))
|
||||||
if (strcmp(plugin->name, plugin_to_register->name) == 0)
|
return FALSE;
|
||||||
{
|
|
||||||
WLog_ERR(TAG, "can not register plugin '%s', it is already registered!", plugin->name);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ArrayList_Add(plugins_list, plugin_to_register) < 0)
|
if (ArrayList_Add(plugins_list, plugin_to_register) < 0)
|
||||||
{
|
{
|
||||||
@ -266,28 +284,43 @@ static BOOL pf_modules_register_plugin(proxyPlugin* plugin_to_register)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL pf_modules_load_ArrayList_ForEachFkt(void* data, size_t index, va_list ap)
|
||||||
|
{
|
||||||
|
proxyPlugin* plugin = (proxyPlugin*)data;
|
||||||
|
const char* plugin_name = va_arg(ap, const char*);
|
||||||
|
|
||||||
|
WINPR_UNUSED(index);
|
||||||
|
WINPR_UNUSED(ap);
|
||||||
|
|
||||||
|
if (strcmp(plugin->name, plugin_name) == 0)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL pf_modules_is_plugin_loaded(const char* plugin_name)
|
BOOL pf_modules_is_plugin_loaded(const char* plugin_name)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
proxyPlugin* plugin;
|
|
||||||
|
|
||||||
if (plugins_list == NULL)
|
if (plugins_list == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
ArrayList_ForEach(plugins_list, proxyPlugin*, i, plugin)
|
return ArrayList_ForEach(plugins_list, pf_modules_load_ArrayList_ForEachFkt, plugin_name);
|
||||||
{
|
}
|
||||||
if (strcmp(plugin->name, plugin_name) == 0)
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
static BOOL pf_modules_print_ArrayList_ForEachFkt(void* data, size_t index, va_list ap)
|
||||||
|
{
|
||||||
|
proxyPlugin* plugin = (proxyPlugin*)data;
|
||||||
|
const char* plugin_name = va_arg(ap, const char*);
|
||||||
|
|
||||||
|
WINPR_UNUSED(index);
|
||||||
|
WINPR_UNUSED(ap);
|
||||||
|
|
||||||
|
WLog_INFO(TAG, "\tName: %s", plugin->name);
|
||||||
|
WLog_INFO(TAG, "\tDescription: %s", plugin->description);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pf_modules_list_loaded_plugins(void)
|
void pf_modules_list_loaded_plugins(void)
|
||||||
{
|
{
|
||||||
size_t count;
|
size_t count;
|
||||||
int i;
|
|
||||||
proxyPlugin* plugin;
|
|
||||||
|
|
||||||
if (plugins_list == NULL)
|
if (plugins_list == NULL)
|
||||||
return;
|
return;
|
||||||
@ -297,12 +330,7 @@ void pf_modules_list_loaded_plugins(void)
|
|||||||
if (count > 0)
|
if (count > 0)
|
||||||
WLog_INFO(TAG, "Loaded plugins:");
|
WLog_INFO(TAG, "Loaded plugins:");
|
||||||
|
|
||||||
ArrayList_ForEach(plugins_list, proxyPlugin*, i, plugin)
|
ArrayList_ForEach(plugins_list, pf_modules_print_ArrayList_ForEachFkt);
|
||||||
{
|
|
||||||
|
|
||||||
WLog_INFO(TAG, "\tName: %s", plugin->name);
|
|
||||||
WLog_INFO(TAG, "\tDescription: %s", plugin->description);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static proxyPluginsManager plugins_manager = { pf_modules_register_plugin,
|
static proxyPluginsManager plugins_manager = { pf_modules_register_plugin,
|
||||||
@ -398,34 +426,41 @@ error:
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL pf_modules_free_ArrayList_ForEachFkt(void* data, size_t index, va_list ap)
|
||||||
|
{
|
||||||
|
proxyPlugin* plugin = (proxyPlugin*)data;
|
||||||
|
const char* plugin_name = va_arg(ap, const char*);
|
||||||
|
|
||||||
|
WINPR_UNUSED(index);
|
||||||
|
WINPR_UNUSED(ap);
|
||||||
|
|
||||||
|
if (!IFCALLRESULT(TRUE, plugin->PluginUnload))
|
||||||
|
WLog_WARN(TAG, "PluginUnload failed for plugin '%s'", plugin->name);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL pf_modules_free_handles_ArrayList_ForEachFkt(void* data, size_t index, va_list ap)
|
||||||
|
{
|
||||||
|
HANDLE handle = (HANDLE)data;
|
||||||
|
|
||||||
|
WINPR_UNUSED(index);
|
||||||
|
WINPR_UNUSED(ap);
|
||||||
|
if (handle)
|
||||||
|
FreeLibrary(handle);
|
||||||
|
}
|
||||||
|
|
||||||
void pf_modules_free(void)
|
void pf_modules_free(void)
|
||||||
{
|
{
|
||||||
int index;
|
|
||||||
|
|
||||||
if (plugins_list)
|
if (plugins_list)
|
||||||
{
|
{
|
||||||
proxyPlugin* plugin;
|
ArrayList_ForEach(plugins_list, pf_modules_free_ArrayList_ForEachFkt);
|
||||||
|
|
||||||
ArrayList_ForEach(plugins_list, proxyPlugin*, index, plugin)
|
|
||||||
{
|
|
||||||
if (!IFCALLRESULT(TRUE, plugin->PluginUnload))
|
|
||||||
WLog_WARN(TAG, "PluginUnload failed for plugin '%s'", plugin->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList_Free(plugins_list);
|
ArrayList_Free(plugins_list);
|
||||||
plugins_list = NULL;
|
plugins_list = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handles_list)
|
if (handles_list)
|
||||||
{
|
{
|
||||||
HANDLE handle;
|
ArrayList_ForEach(handles_list, pf_modules_free_handles_ArrayList_ForEachFkt);
|
||||||
|
|
||||||
ArrayList_ForEach(handles_list, HANDLE, index, handle)
|
|
||||||
{
|
|
||||||
if (handle)
|
|
||||||
FreeLibrary(handle);
|
|
||||||
};
|
|
||||||
|
|
||||||
ArrayList_Free(handles_list);
|
ArrayList_Free(handles_list);
|
||||||
handles_list = NULL;
|
handles_list = NULL;
|
||||||
}
|
}
|
||||||
|
@ -582,6 +582,7 @@ static void pf_server_clients_list_client_free(void* obj)
|
|||||||
|
|
||||||
proxyServer* pf_server_new(proxyConfig* config)
|
proxyServer* pf_server_new(proxyConfig* config)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
proxyServer* server;
|
proxyServer* server;
|
||||||
|
|
||||||
if (!config)
|
if (!config)
|
||||||
@ -601,7 +602,8 @@ proxyServer* pf_server_new(proxyConfig* config)
|
|||||||
if (!server->clients)
|
if (!server->clients)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
server->clients->object.fnObjectFree = pf_server_clients_list_client_free;
|
obj = ArrayList_Object(server->clients);
|
||||||
|
obj->fnObjectFree = pf_server_clients_list_client_free;
|
||||||
|
|
||||||
server->waitGroup = CountdownEvent_New(0);
|
server->waitGroup = CountdownEvent_New(0);
|
||||||
if (!server->waitGroup)
|
if (!server->waitGroup)
|
||||||
|
@ -125,10 +125,17 @@ void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem)
|
|||||||
|
|
||||||
if (subsystem->MsgPipe)
|
if (subsystem->MsgPipe)
|
||||||
{
|
{
|
||||||
|
wObject* obj1;
|
||||||
|
wObject* obj2;
|
||||||
/* Release resource in messages before free */
|
/* Release resource in messages before free */
|
||||||
subsystem->MsgPipe->In->object.fnObjectFree = shadow_subsystem_free_queued_message;
|
obj1 = MessageQueue_Object(subsystem->MsgPipe->In);
|
||||||
|
obj2 = MessageQueue_Object(subsystem->MsgPipe->Out);
|
||||||
|
if (obj1)
|
||||||
|
obj1->fnObjectFree = shadow_subsystem_free_queued_message;
|
||||||
MessageQueue_Clear(subsystem->MsgPipe->In);
|
MessageQueue_Clear(subsystem->MsgPipe->In);
|
||||||
subsystem->MsgPipe->Out->object.fnObjectFree = shadow_subsystem_free_queued_message;
|
|
||||||
|
if (obj2)
|
||||||
|
obj2->fnObjectFree = shadow_subsystem_free_queued_message;
|
||||||
MessageQueue_Clear(subsystem->MsgPipe->Out);
|
MessageQueue_Clear(subsystem->MsgPipe->Out);
|
||||||
MessagePipe_Free(subsystem->MsgPipe);
|
MessagePipe_Free(subsystem->MsgPipe);
|
||||||
subsystem->MsgPipe = NULL;
|
subsystem->MsgPipe = NULL;
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include <winpr/winpr.h>
|
#include <winpr/winpr.h>
|
||||||
#include <winpr/wtypes.h>
|
#include <winpr/wtypes.h>
|
||||||
@ -36,7 +37,7 @@ extern "C"
|
|||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void* (*OBJECT_NEW_FN)(void* val);
|
typedef void* (*OBJECT_NEW_FN)(const void* val);
|
||||||
typedef void (*OBJECT_INIT_FN)(void* obj);
|
typedef void (*OBJECT_INIT_FN)(void* obj);
|
||||||
typedef void (*OBJECT_UNINIT_FN)(void* obj);
|
typedef void (*OBJECT_UNINIT_FN)(void* obj);
|
||||||
typedef void (*OBJECT_FREE_FN)(void* obj);
|
typedef void (*OBJECT_FREE_FN)(void* obj);
|
||||||
@ -54,23 +55,6 @@ extern "C"
|
|||||||
|
|
||||||
/* System.Collections.Queue */
|
/* System.Collections.Queue */
|
||||||
|
|
||||||
/* WARNING: Do not access structs directly, the API will be reworked
|
|
||||||
* to make this opaque. */
|
|
||||||
struct _wQueue
|
|
||||||
{
|
|
||||||
int capacity;
|
|
||||||
int growthFactor;
|
|
||||||
BOOL synchronized;
|
|
||||||
|
|
||||||
int head;
|
|
||||||
int tail;
|
|
||||||
int size;
|
|
||||||
void** array;
|
|
||||||
CRITICAL_SECTION lock;
|
|
||||||
HANDLE event;
|
|
||||||
|
|
||||||
wObject object;
|
|
||||||
};
|
|
||||||
typedef struct _wQueue wQueue;
|
typedef struct _wQueue wQueue;
|
||||||
|
|
||||||
WINPR_API int Queue_Count(wQueue* queue);
|
WINPR_API int Queue_Count(wQueue* queue);
|
||||||
@ -80,11 +64,11 @@ extern "C"
|
|||||||
|
|
||||||
WINPR_API HANDLE Queue_Event(wQueue* queue);
|
WINPR_API HANDLE Queue_Event(wQueue* queue);
|
||||||
|
|
||||||
#define Queue_Object(_queue) (&_queue->object)
|
WINPR_API wObject* Queue_Object(wQueue* queue);
|
||||||
|
|
||||||
WINPR_API void Queue_Clear(wQueue* queue);
|
WINPR_API void Queue_Clear(wQueue* queue);
|
||||||
|
|
||||||
WINPR_API BOOL Queue_Contains(wQueue* queue, void* obj);
|
WINPR_API BOOL Queue_Contains(wQueue* queue, const void* obj);
|
||||||
|
|
||||||
WINPR_API BOOL Queue_Enqueue(wQueue* queue, void* obj);
|
WINPR_API BOOL Queue_Enqueue(wQueue* queue, void* obj);
|
||||||
WINPR_API void* Queue_Dequeue(wQueue* queue);
|
WINPR_API void* Queue_Dequeue(wQueue* queue);
|
||||||
@ -116,25 +100,11 @@ extern "C"
|
|||||||
|
|
||||||
/* System.Collections.ArrayList */
|
/* System.Collections.ArrayList */
|
||||||
|
|
||||||
/* WARNING: Do not access structs directly, the API will be reworked
|
|
||||||
* to make this opaque. */
|
|
||||||
struct _wArrayList
|
|
||||||
{
|
|
||||||
int capacity;
|
|
||||||
int growthFactor;
|
|
||||||
BOOL synchronized;
|
|
||||||
|
|
||||||
int size;
|
|
||||||
void** array;
|
|
||||||
CRITICAL_SECTION lock;
|
|
||||||
|
|
||||||
wObject object;
|
|
||||||
};
|
|
||||||
typedef struct _wArrayList wArrayList;
|
typedef struct _wArrayList wArrayList;
|
||||||
|
|
||||||
WINPR_API int ArrayList_Capacity(wArrayList* arrayList);
|
WINPR_API size_t ArrayList_Capacity(wArrayList* arrayList);
|
||||||
WINPR_API int ArrayList_Count(wArrayList* arrayList);
|
WINPR_API size_t ArrayList_Count(wArrayList* arrayList);
|
||||||
WINPR_API int ArrayList_Items(wArrayList* arrayList, ULONG_PTR** ppItems);
|
WINPR_API size_t ArrayList_Items(wArrayList* arrayList, ULONG_PTR** ppItems);
|
||||||
WINPR_API BOOL ArrayList_IsFixedSized(wArrayList* arrayList);
|
WINPR_API BOOL ArrayList_IsFixedSized(wArrayList* arrayList);
|
||||||
WINPR_API BOOL ArrayList_IsReadOnly(wArrayList* arrayList);
|
WINPR_API BOOL ArrayList_IsReadOnly(wArrayList* arrayList);
|
||||||
WINPR_API BOOL ArrayList_IsSynchronized(wArrayList* arrayList);
|
WINPR_API BOOL ArrayList_IsSynchronized(wArrayList* arrayList);
|
||||||
@ -142,28 +112,28 @@ extern "C"
|
|||||||
WINPR_API void ArrayList_Lock(wArrayList* arrayList);
|
WINPR_API void ArrayList_Lock(wArrayList* arrayList);
|
||||||
WINPR_API void ArrayList_Unlock(wArrayList* arrayList);
|
WINPR_API void ArrayList_Unlock(wArrayList* arrayList);
|
||||||
|
|
||||||
WINPR_API void* ArrayList_GetItem(wArrayList* arrayList, int index);
|
WINPR_API void* ArrayList_GetItem(wArrayList* arrayList, size_t index);
|
||||||
WINPR_API void ArrayList_SetItem(wArrayList* arrayList, int index, void* obj);
|
WINPR_API void ArrayList_SetItem(wArrayList* arrayList, size_t index, const void* obj);
|
||||||
|
|
||||||
#define ArrayList_Object(_arrayList) (&_arrayList->object)
|
WINPR_API wObject* ArrayList_Object(wArrayList* arrayList);
|
||||||
|
|
||||||
#define ArrayList_ForEach(_lst, _type, index, value) \
|
typedef BOOL(ArrayList_ForEachFkt)(void* data, size_t index, va_list ap);
|
||||||
for (index = 0; \
|
|
||||||
index < ArrayList_Count(_lst) && (value = (_type)ArrayList_GetItem(_lst, index)); \
|
WINPR_API BOOL ArrayList_ForEach(wArrayList* arrayList, ArrayList_ForEachFkt fkt, ...);
|
||||||
index++)
|
|
||||||
|
|
||||||
WINPR_API void ArrayList_Clear(wArrayList* arrayList);
|
WINPR_API void ArrayList_Clear(wArrayList* arrayList);
|
||||||
WINPR_API BOOL ArrayList_Contains(wArrayList* arrayList, void* obj);
|
WINPR_API BOOL ArrayList_Contains(wArrayList* arrayList, const void* obj);
|
||||||
|
|
||||||
WINPR_API int ArrayList_Add(wArrayList* arrayList, void* obj);
|
WINPR_API int ArrayList_Add(wArrayList* arrayList, void* obj);
|
||||||
WINPR_API BOOL ArrayList_Insert(wArrayList* arrayList, int index, void* obj);
|
WINPR_API BOOL ArrayList_Insert(wArrayList* arrayList, size_t index, const void* obj);
|
||||||
|
|
||||||
WINPR_API BOOL ArrayList_Remove(wArrayList* arrayList, void* obj);
|
WINPR_API BOOL ArrayList_Remove(wArrayList* arrayList, const void* obj);
|
||||||
WINPR_API BOOL ArrayList_RemoveAt(wArrayList* arrayList, int index);
|
WINPR_API BOOL ArrayList_RemoveAt(wArrayList* arrayList, size_t index);
|
||||||
|
|
||||||
WINPR_API int ArrayList_IndexOf(wArrayList* arrayList, void* obj, int startIndex, int count);
|
WINPR_API SSIZE_T ArrayList_IndexOf(wArrayList* arrayList, const void* obj, SSIZE_T startIndex,
|
||||||
WINPR_API int ArrayList_LastIndexOf(wArrayList* arrayList, void* obj, int startIndex,
|
SSIZE_T count);
|
||||||
int count);
|
WINPR_API SSIZE_T ArrayList_LastIndexOf(wArrayList* arrayList, const void* obj,
|
||||||
|
SSIZE_T startIndex, SSIZE_T count);
|
||||||
|
|
||||||
WINPR_API wArrayList* ArrayList_New(BOOL synchronized);
|
WINPR_API wArrayList* ArrayList_New(BOOL synchronized);
|
||||||
WINPR_API void ArrayList_Free(wArrayList* arrayList);
|
WINPR_API void ArrayList_Free(wArrayList* arrayList);
|
||||||
@ -387,68 +357,27 @@ extern "C"
|
|||||||
|
|
||||||
/* BufferPool */
|
/* BufferPool */
|
||||||
|
|
||||||
/* WARNING: Do not access structs directly, the API will be reworked
|
|
||||||
* to make this opaque. */
|
|
||||||
struct _wBufferPoolItem
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
void* buffer;
|
|
||||||
};
|
|
||||||
typedef struct _wBufferPoolItem wBufferPoolItem;
|
|
||||||
|
|
||||||
/* WARNING: Do not access structs directly, the API will be reworked
|
|
||||||
* to make this opaque. */
|
|
||||||
struct _wBufferPool
|
|
||||||
{
|
|
||||||
int fixedSize;
|
|
||||||
DWORD alignment;
|
|
||||||
BOOL synchronized;
|
|
||||||
CRITICAL_SECTION lock;
|
|
||||||
|
|
||||||
int size;
|
|
||||||
int capacity;
|
|
||||||
void** array;
|
|
||||||
|
|
||||||
int aSize;
|
|
||||||
int aCapacity;
|
|
||||||
wBufferPoolItem* aArray;
|
|
||||||
|
|
||||||
int uSize;
|
|
||||||
int uCapacity;
|
|
||||||
wBufferPoolItem* uArray;
|
|
||||||
};
|
|
||||||
typedef struct _wBufferPool wBufferPool;
|
typedef struct _wBufferPool wBufferPool;
|
||||||
|
|
||||||
WINPR_API int BufferPool_GetPoolSize(wBufferPool* pool);
|
WINPR_API SSIZE_T BufferPool_GetPoolSize(wBufferPool* pool);
|
||||||
WINPR_API int BufferPool_GetBufferSize(wBufferPool* pool, void* buffer);
|
WINPR_API SSIZE_T BufferPool_GetBufferSize(wBufferPool* pool, const void* buffer);
|
||||||
|
|
||||||
WINPR_API void* BufferPool_Take(wBufferPool* pool, int bufferSize);
|
WINPR_API void* BufferPool_Take(wBufferPool* pool, SSIZE_T bufferSize);
|
||||||
WINPR_API BOOL BufferPool_Return(wBufferPool* pool, void* buffer);
|
WINPR_API BOOL BufferPool_Return(wBufferPool* pool, void* buffer);
|
||||||
WINPR_API void BufferPool_Clear(wBufferPool* pool);
|
WINPR_API void BufferPool_Clear(wBufferPool* pool);
|
||||||
|
|
||||||
WINPR_API wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment);
|
WINPR_API wBufferPool* BufferPool_New(BOOL synchronized, SSIZE_T fixedSize, DWORD alignment);
|
||||||
WINPR_API void BufferPool_Free(wBufferPool* pool);
|
WINPR_API void BufferPool_Free(wBufferPool* pool);
|
||||||
|
|
||||||
/* ObjectPool */
|
/* ObjectPool */
|
||||||
|
|
||||||
/* WARNING: Do not access structs directly, the API will be reworked
|
|
||||||
* to make this opaque. */
|
|
||||||
struct _wObjectPool
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
int capacity;
|
|
||||||
void** array;
|
|
||||||
CRITICAL_SECTION lock;
|
|
||||||
wObject object;
|
|
||||||
BOOL synchronized;
|
|
||||||
};
|
|
||||||
typedef struct _wObjectPool wObjectPool;
|
typedef struct _wObjectPool wObjectPool;
|
||||||
|
|
||||||
WINPR_API void* ObjectPool_Take(wObjectPool* pool);
|
WINPR_API void* ObjectPool_Take(wObjectPool* pool);
|
||||||
WINPR_API void ObjectPool_Return(wObjectPool* pool, void* obj);
|
WINPR_API void ObjectPool_Return(wObjectPool* pool, void* obj);
|
||||||
WINPR_API void ObjectPool_Clear(wObjectPool* pool);
|
WINPR_API void ObjectPool_Clear(wObjectPool* pool);
|
||||||
|
|
||||||
#define ObjectPool_Object(_pool) (&_pool->object)
|
WINPR_API wObject* ObjectPool_Object(wObjectPool* pool);
|
||||||
|
|
||||||
WINPR_API wObjectPool* ObjectPool_New(BOOL synchronized);
|
WINPR_API wObjectPool* ObjectPool_New(BOOL synchronized);
|
||||||
WINPR_API void ObjectPool_Free(wObjectPool* pool);
|
WINPR_API void ObjectPool_Free(wObjectPool* pool);
|
||||||
@ -469,30 +398,16 @@ extern "C"
|
|||||||
MESSAGE_FREE_FN Free;
|
MESSAGE_FREE_FN Free;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* WARNING: Do not access structs directly, the API will be reworked
|
|
||||||
* to make this opaque. */
|
|
||||||
struct _wMessageQueue
|
|
||||||
{
|
|
||||||
int head;
|
|
||||||
int tail;
|
|
||||||
int size;
|
|
||||||
int capacity;
|
|
||||||
BOOL closed;
|
|
||||||
wMessage* array;
|
|
||||||
CRITICAL_SECTION lock;
|
|
||||||
HANDLE event;
|
|
||||||
|
|
||||||
wObject object;
|
|
||||||
};
|
|
||||||
typedef struct _wMessageQueue wMessageQueue;
|
typedef struct _wMessageQueue wMessageQueue;
|
||||||
|
|
||||||
#define WMQ_QUIT 0xFFFFFFFF
|
#define WMQ_QUIT 0xFFFFFFFF
|
||||||
|
|
||||||
|
WINPR_API wObject* MessageQueue_Object(wMessageQueue* queue);
|
||||||
WINPR_API HANDLE MessageQueue_Event(wMessageQueue* queue);
|
WINPR_API HANDLE MessageQueue_Event(wMessageQueue* queue);
|
||||||
WINPR_API BOOL MessageQueue_Wait(wMessageQueue* queue);
|
WINPR_API BOOL MessageQueue_Wait(wMessageQueue* queue);
|
||||||
WINPR_API int MessageQueue_Size(wMessageQueue* queue);
|
WINPR_API size_t MessageQueue_Size(wMessageQueue* queue);
|
||||||
|
|
||||||
WINPR_API BOOL MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message);
|
WINPR_API BOOL MessageQueue_Dispatch(wMessageQueue* queue, const wMessage* message);
|
||||||
WINPR_API BOOL MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* wParam,
|
WINPR_API BOOL MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* wParam,
|
||||||
void* lParam);
|
void* lParam);
|
||||||
WINPR_API BOOL MessageQueue_PostQuit(wMessageQueue* queue, int nExitCode);
|
WINPR_API BOOL MessageQueue_PostQuit(wMessageQueue* queue, int nExitCode);
|
||||||
@ -618,24 +533,13 @@ extern "C"
|
|||||||
|
|
||||||
#define DEFINE_EVENT_ENTRY(_name) { #_name, { sizeof(_name##EventArgs), NULL }, 0, { NULL } },
|
#define DEFINE_EVENT_ENTRY(_name) { #_name, { sizeof(_name##EventArgs), NULL }, 0, { NULL } },
|
||||||
|
|
||||||
/* WARNING: Do not access structs directly, the API will be reworked
|
|
||||||
* to make this opaque. */
|
|
||||||
struct _wPubSub
|
|
||||||
{
|
|
||||||
CRITICAL_SECTION lock;
|
|
||||||
BOOL synchronized;
|
|
||||||
|
|
||||||
int size;
|
|
||||||
int count;
|
|
||||||
wEventType* events;
|
|
||||||
};
|
|
||||||
typedef struct _wPubSub wPubSub;
|
typedef struct _wPubSub wPubSub;
|
||||||
|
|
||||||
WINPR_API void PubSub_Lock(wPubSub* pubSub);
|
WINPR_API void PubSub_Lock(wPubSub* pubSub);
|
||||||
WINPR_API void PubSub_Unlock(wPubSub* pubSub);
|
WINPR_API void PubSub_Unlock(wPubSub* pubSub);
|
||||||
|
|
||||||
WINPR_API wEventType* PubSub_GetEventTypes(wPubSub* pubSub, int* count);
|
WINPR_API wEventType* PubSub_GetEventTypes(wPubSub* pubSub, size_t* count);
|
||||||
WINPR_API void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, int count);
|
WINPR_API void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, size_t count);
|
||||||
WINPR_API wEventType* PubSub_FindEventType(wPubSub* pubSub, const char* EventName);
|
WINPR_API wEventType* PubSub_FindEventType(wPubSub* pubSub, const char* EventName);
|
||||||
|
|
||||||
WINPR_API int PubSub_Subscribe(wPubSub* pubSub, const char* EventName,
|
WINPR_API int PubSub_Subscribe(wPubSub* pubSub, const char* EventName,
|
||||||
@ -650,28 +554,6 @@ extern "C"
|
|||||||
WINPR_API void PubSub_Free(wPubSub* pubSub);
|
WINPR_API void PubSub_Free(wPubSub* pubSub);
|
||||||
|
|
||||||
/* BipBuffer */
|
/* BipBuffer */
|
||||||
|
|
||||||
/* WARNING: Do not access structs directly, the API will be reworked
|
|
||||||
* to make this opaque. */
|
|
||||||
struct _wBipBlock
|
|
||||||
{
|
|
||||||
size_t index;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
typedef struct _wBipBlock wBipBlock;
|
|
||||||
|
|
||||||
/* WARNING: Do not access structs directly, the API will be reworked
|
|
||||||
* to make this opaque. */
|
|
||||||
struct _wBipBuffer
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
BYTE* buffer;
|
|
||||||
size_t pageSize;
|
|
||||||
wBipBlock blockA;
|
|
||||||
wBipBlock blockB;
|
|
||||||
wBipBlock readR;
|
|
||||||
wBipBlock writeR;
|
|
||||||
};
|
|
||||||
typedef struct _wBipBuffer wBipBuffer;
|
typedef struct _wBipBuffer wBipBuffer;
|
||||||
|
|
||||||
WINPR_API BOOL BipBuffer_Grow(wBipBuffer* bb, size_t size);
|
WINPR_API BOOL BipBuffer_Grow(wBipBuffer* bb, size_t size);
|
||||||
|
@ -659,6 +659,7 @@ static void* convert_filedescriptors_to_uri_list(wClipboard* clipboard, UINT32 f
|
|||||||
|
|
||||||
static BOOL register_file_formats_and_synthesizers(wClipboard* clipboard)
|
static BOOL register_file_formats_and_synthesizers(wClipboard* clipboard)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
UINT32 file_group_format_id;
|
UINT32 file_group_format_id;
|
||||||
UINT32 local_file_format_id;
|
UINT32 local_file_format_id;
|
||||||
file_group_format_id = ClipboardRegisterFormat(clipboard, "FileGroupDescriptorW");
|
file_group_format_id = ClipboardRegisterFormat(clipboard, "FileGroupDescriptorW");
|
||||||
@ -672,7 +673,10 @@ static BOOL register_file_formats_and_synthesizers(wClipboard* clipboard)
|
|||||||
if (!clipboard->localFiles)
|
if (!clipboard->localFiles)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
ArrayList_Object(clipboard->localFiles)->fnObjectFree = free_posix_file;
|
obj = ArrayList_Object(clipboard->localFiles);
|
||||||
|
if (!obj)
|
||||||
|
goto error;
|
||||||
|
obj->fnObjectFree = free_posix_file;
|
||||||
|
|
||||||
if (!ClipboardRegisterSynthesizer(clipboard, local_file_format_id, file_group_format_id,
|
if (!ClipboardRegisterSynthesizer(clipboard, local_file_format_id, file_group_format_id,
|
||||||
convert_uri_list_to_filedescriptors))
|
convert_uri_list_to_filedescriptors))
|
||||||
|
@ -106,6 +106,7 @@ static void threads_close(void* thread)
|
|||||||
static BOOL InitializeThreadpool(PTP_POOL pool)
|
static BOOL InitializeThreadpool(PTP_POOL pool)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
wObject* obj;
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
|
|
||||||
if (pool->Threads)
|
if (pool->Threads)
|
||||||
@ -126,7 +127,8 @@ static BOOL InitializeThreadpool(PTP_POOL pool)
|
|||||||
if (!(pool->Threads = ArrayList_New(TRUE)))
|
if (!(pool->Threads = ArrayList_New(TRUE)))
|
||||||
goto fail_thread_array;
|
goto fail_thread_array;
|
||||||
|
|
||||||
pool->Threads->object.fnObjectFree = threads_close;
|
obj = ArrayList_Object(pool->Threads);
|
||||||
|
obj->fnObjectFree = threads_close;
|
||||||
|
|
||||||
for (index = 0; index < 4; index++)
|
for (index = 0; index < 4; index++)
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,19 @@
|
|||||||
|
|
||||||
#include <winpr/collections.h>
|
#include <winpr/collections.h>
|
||||||
|
|
||||||
|
struct _wArrayList
|
||||||
|
{
|
||||||
|
size_t capacity;
|
||||||
|
size_t growthFactor;
|
||||||
|
BOOL synchronized;
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
void** array;
|
||||||
|
CRITICAL_SECTION lock;
|
||||||
|
|
||||||
|
wObject object;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C equivalent of the C# ArrayList Class:
|
* C equivalent of the C# ArrayList Class:
|
||||||
* http://msdn.microsoft.com/en-us/library/system.collections.arraylist.aspx
|
* http://msdn.microsoft.com/en-us/library/system.collections.arraylist.aspx
|
||||||
@ -38,7 +51,7 @@
|
|||||||
* Gets or sets the number of elements that the ArrayList can contain.
|
* Gets or sets the number of elements that the ArrayList can contain.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ArrayList_Capacity(wArrayList* arrayList)
|
size_t ArrayList_Capacity(wArrayList* arrayList)
|
||||||
{
|
{
|
||||||
return arrayList->capacity;
|
return arrayList->capacity;
|
||||||
}
|
}
|
||||||
@ -47,7 +60,7 @@ int ArrayList_Capacity(wArrayList* arrayList)
|
|||||||
* Gets the number of elements actually contained in the ArrayList.
|
* Gets the number of elements actually contained in the ArrayList.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ArrayList_Count(wArrayList* arrayList)
|
size_t ArrayList_Count(wArrayList* arrayList)
|
||||||
{
|
{
|
||||||
return arrayList->size;
|
return arrayList->size;
|
||||||
}
|
}
|
||||||
@ -56,7 +69,7 @@ int ArrayList_Count(wArrayList* arrayList)
|
|||||||
* Gets the internal list of items contained in the ArrayList.
|
* Gets the internal list of items contained in the ArrayList.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ArrayList_Items(wArrayList* arrayList, ULONG_PTR** ppItems)
|
size_t ArrayList_Items(wArrayList* arrayList, ULONG_PTR** ppItems)
|
||||||
{
|
{
|
||||||
*ppItems = (ULONG_PTR*)arrayList->array;
|
*ppItems = (ULONG_PTR*)arrayList->array;
|
||||||
return arrayList->size;
|
return arrayList->size;
|
||||||
@ -93,6 +106,12 @@ BOOL ArrayList_IsSynchronized(wArrayList* arrayList)
|
|||||||
* Lock access to the ArrayList
|
* Lock access to the ArrayList
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void ArrayList_Lock_Conditional(wArrayList* arrayList)
|
||||||
|
{
|
||||||
|
if (arrayList->synchronized)
|
||||||
|
EnterCriticalSection(&arrayList->lock);
|
||||||
|
}
|
||||||
|
|
||||||
void ArrayList_Lock(wArrayList* arrayList)
|
void ArrayList_Lock(wArrayList* arrayList)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&arrayList->lock);
|
EnterCriticalSection(&arrayList->lock);
|
||||||
@ -102,6 +121,12 @@ void ArrayList_Lock(wArrayList* arrayList)
|
|||||||
* Unlock access to the ArrayList
|
* Unlock access to the ArrayList
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void ArrayList_Unlock_Conditional(wArrayList* arrayList)
|
||||||
|
{
|
||||||
|
if (arrayList->synchronized)
|
||||||
|
LeaveCriticalSection(&arrayList->lock);
|
||||||
|
}
|
||||||
|
|
||||||
void ArrayList_Unlock(wArrayList* arrayList)
|
void ArrayList_Unlock(wArrayList* arrayList)
|
||||||
{
|
{
|
||||||
LeaveCriticalSection(&arrayList->lock);
|
LeaveCriticalSection(&arrayList->lock);
|
||||||
@ -111,7 +136,7 @@ void ArrayList_Unlock(wArrayList* arrayList)
|
|||||||
* Gets the element at the specified index.
|
* Gets the element at the specified index.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void* ArrayList_GetItem(wArrayList* arrayList, int index)
|
void* ArrayList_GetItem(wArrayList* arrayList, size_t index)
|
||||||
{
|
{
|
||||||
void* obj = NULL;
|
void* obj = NULL;
|
||||||
|
|
||||||
@ -127,18 +152,43 @@ void* ArrayList_GetItem(wArrayList* arrayList, int index)
|
|||||||
* Sets the element at the specified index.
|
* Sets the element at the specified index.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ArrayList_SetItem(wArrayList* arrayList, int index, void* obj)
|
void ArrayList_SetItem(wArrayList* arrayList, size_t index, const void* obj)
|
||||||
{
|
{
|
||||||
if ((index >= 0) && (index < arrayList->size))
|
if ((index >= 0) && (index < arrayList->size))
|
||||||
{
|
{
|
||||||
arrayList->array[index] = obj;
|
if (arrayList->object.fnObjectNew)
|
||||||
|
arrayList->array[index] = arrayList->object.fnObjectNew(obj);
|
||||||
|
else
|
||||||
|
arrayList->array[index] = (void*)obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Methods
|
* Methods
|
||||||
*/
|
*/
|
||||||
|
static BOOL ArrayList_EnsureCapacity(wArrayList* arrayList, size_t count)
|
||||||
|
{
|
||||||
|
if (!arrayList)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (arrayList->size + count > arrayList->capacity)
|
||||||
|
{
|
||||||
|
void** newArray;
|
||||||
|
size_t newCapacity = arrayList->capacity * arrayList->growthFactor;
|
||||||
|
if (newCapacity < arrayList->size + count)
|
||||||
|
newCapacity = arrayList->size + count;
|
||||||
|
|
||||||
|
newArray = (void**)realloc(arrayList->array, sizeof(void*) * newCapacity);
|
||||||
|
|
||||||
|
if (!newArray)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
arrayList->array = newArray;
|
||||||
|
arrayList->capacity = newCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Shift a section of the list.
|
* Shift a section of the list.
|
||||||
*/
|
*/
|
||||||
@ -147,18 +197,8 @@ static BOOL ArrayList_Shift(wArrayList* arrayList, int index, int count)
|
|||||||
{
|
{
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
if (arrayList->size + count > arrayList->capacity)
|
if (!ArrayList_EnsureCapacity(arrayList, count))
|
||||||
{
|
return FALSE;
|
||||||
void** newArray;
|
|
||||||
int newCapacity = arrayList->capacity * arrayList->growthFactor;
|
|
||||||
newArray = (void**)realloc(arrayList->array, sizeof(void*) * newCapacity);
|
|
||||||
|
|
||||||
if (!newArray)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
arrayList->array = newArray;
|
|
||||||
arrayList->capacity = newCapacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
MoveMemory(&arrayList->array[index + count], &arrayList->array[index],
|
MoveMemory(&arrayList->array[index + count], &arrayList->array[index],
|
||||||
(arrayList->size - index) * sizeof(void*));
|
(arrayList->size - index) * sizeof(void*));
|
||||||
@ -166,7 +206,7 @@ static BOOL ArrayList_Shift(wArrayList* arrayList, int index, int count)
|
|||||||
}
|
}
|
||||||
else if (count < 0)
|
else if (count < 0)
|
||||||
{
|
{
|
||||||
int chunk = arrayList->size - index + count;
|
INT64 chunk = arrayList->size - index + count;
|
||||||
|
|
||||||
if (chunk > 0)
|
if (chunk > 0)
|
||||||
MoveMemory(&arrayList->array[index], &arrayList->array[index - count],
|
MoveMemory(&arrayList->array[index], &arrayList->array[index - count],
|
||||||
@ -184,10 +224,9 @@ static BOOL ArrayList_Shift(wArrayList* arrayList, int index, int count)
|
|||||||
|
|
||||||
void ArrayList_Clear(wArrayList* arrayList)
|
void ArrayList_Clear(wArrayList* arrayList)
|
||||||
{
|
{
|
||||||
int index;
|
size_t index;
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Lock_Conditional(arrayList);
|
||||||
EnterCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
for (index = 0; index < arrayList->size; index++)
|
for (index = 0; index < arrayList->size; index++)
|
||||||
{
|
{
|
||||||
@ -199,21 +238,19 @@ void ArrayList_Clear(wArrayList* arrayList)
|
|||||||
|
|
||||||
arrayList->size = 0;
|
arrayList->size = 0;
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Unlock_Conditional(arrayList);
|
||||||
LeaveCriticalSection(&arrayList->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether an element is in the ArrayList.
|
* Determines whether an element is in the ArrayList.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL ArrayList_Contains(wArrayList* arrayList, void* obj)
|
BOOL ArrayList_Contains(wArrayList* arrayList, const void* obj)
|
||||||
{
|
{
|
||||||
int index;
|
size_t index;
|
||||||
BOOL rc = FALSE;
|
BOOL rc = FALSE;
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Lock_Conditional(arrayList);
|
||||||
EnterCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
for (index = 0; index < arrayList->size; index++)
|
for (index = 0; index < arrayList->size; index++)
|
||||||
{
|
{
|
||||||
@ -223,8 +260,7 @@ BOOL ArrayList_Contains(wArrayList* arrayList, void* obj)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Unlock_Conditional(arrayList);
|
||||||
LeaveCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -237,28 +273,16 @@ int ArrayList_Add(wArrayList* arrayList, void* obj)
|
|||||||
{
|
{
|
||||||
int index = -1;
|
int index = -1;
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Lock_Conditional(arrayList);
|
||||||
EnterCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
if (arrayList->size + 1 > arrayList->capacity)
|
if (!ArrayList_EnsureCapacity(arrayList, 1))
|
||||||
{
|
goto out;
|
||||||
void** newArray;
|
|
||||||
int newCapacity = arrayList->capacity * arrayList->growthFactor;
|
|
||||||
newArray = (void**)realloc(arrayList->array, sizeof(void*) * newCapacity);
|
|
||||||
|
|
||||||
if (!newArray)
|
index = arrayList->size++;
|
||||||
goto out;
|
ArrayList_SetItem(arrayList, index, obj);
|
||||||
|
|
||||||
arrayList->array = newArray;
|
|
||||||
arrayList->capacity = newCapacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
arrayList->array[arrayList->size++] = obj;
|
|
||||||
index = arrayList->size;
|
|
||||||
out:
|
out:
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Unlock_Conditional(arrayList);
|
||||||
LeaveCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@ -267,12 +291,11 @@ out:
|
|||||||
* Inserts an element into the ArrayList at the specified index.
|
* Inserts an element into the ArrayList at the specified index.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL ArrayList_Insert(wArrayList* arrayList, int index, void* obj)
|
BOOL ArrayList_Insert(wArrayList* arrayList, size_t index, const void* obj)
|
||||||
{
|
{
|
||||||
BOOL ret = TRUE;
|
BOOL ret = TRUE;
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Lock_Conditional(arrayList);
|
||||||
EnterCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
if ((index >= 0) && (index < arrayList->size))
|
if ((index >= 0) && (index < arrayList->size))
|
||||||
{
|
{
|
||||||
@ -282,12 +305,11 @@ BOOL ArrayList_Insert(wArrayList* arrayList, int index, void* obj)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
arrayList->array[index] = obj;
|
ArrayList_SetItem(arrayList, index, obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Unlock_Conditional(arrayList);
|
||||||
LeaveCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -296,14 +318,13 @@ BOOL ArrayList_Insert(wArrayList* arrayList, int index, void* obj)
|
|||||||
* Removes the first occurrence of a specific object from the ArrayList.
|
* Removes the first occurrence of a specific object from the ArrayList.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL ArrayList_Remove(wArrayList* arrayList, void* obj)
|
BOOL ArrayList_Remove(wArrayList* arrayList, const void* obj)
|
||||||
{
|
{
|
||||||
int index;
|
size_t index;
|
||||||
BOOL found = FALSE;
|
BOOL found = FALSE;
|
||||||
BOOL ret = TRUE;
|
BOOL ret = TRUE;
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Lock_Conditional(arrayList);
|
||||||
EnterCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
for (index = 0; index < arrayList->size; index++)
|
for (index = 0; index < arrayList->size; index++)
|
||||||
{
|
{
|
||||||
@ -322,8 +343,7 @@ BOOL ArrayList_Remove(wArrayList* arrayList, void* obj)
|
|||||||
ret = ArrayList_Shift(arrayList, index, -1);
|
ret = ArrayList_Shift(arrayList, index, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Unlock_Conditional(arrayList);
|
||||||
LeaveCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -332,12 +352,11 @@ BOOL ArrayList_Remove(wArrayList* arrayList, void* obj)
|
|||||||
* Removes the element at the specified index of the ArrayList.
|
* Removes the element at the specified index of the ArrayList.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL ArrayList_RemoveAt(wArrayList* arrayList, int index)
|
BOOL ArrayList_RemoveAt(wArrayList* arrayList, size_t index)
|
||||||
{
|
{
|
||||||
BOOL ret = TRUE;
|
BOOL ret = TRUE;
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Lock_Conditional(arrayList);
|
||||||
EnterCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
if ((index >= 0) && (index < arrayList->size))
|
if ((index >= 0) && (index < arrayList->size))
|
||||||
{
|
{
|
||||||
@ -347,8 +366,7 @@ BOOL ArrayList_RemoveAt(wArrayList* arrayList, int index)
|
|||||||
ret = ArrayList_Shift(arrayList, index, -1);
|
ret = ArrayList_Shift(arrayList, index, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Unlock_Conditional(arrayList);
|
||||||
LeaveCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -366,21 +384,22 @@ BOOL ArrayList_RemoveAt(wArrayList* arrayList, int index)
|
|||||||
* the specified index.
|
* the specified index.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ArrayList_IndexOf(wArrayList* arrayList, void* obj, int startIndex, int count)
|
SSIZE_T ArrayList_IndexOf(wArrayList* arrayList, const void* obj, SSIZE_T startIndex, SSIZE_T count)
|
||||||
{
|
{
|
||||||
int index;
|
SSIZE_T index, sindex, cindex;
|
||||||
BOOL found = FALSE;
|
BOOL found = FALSE;
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Lock_Conditional(arrayList);
|
||||||
EnterCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
|
sindex = (size_t)startIndex;
|
||||||
if (startIndex < 0)
|
if (startIndex < 0)
|
||||||
startIndex = 0;
|
sindex = 0;
|
||||||
|
|
||||||
|
cindex = (size_t)count;
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
count = arrayList->size;
|
cindex = arrayList->size;
|
||||||
|
|
||||||
for (index = startIndex; index < startIndex + count; index++)
|
for (index = sindex; index < sindex + cindex; index++)
|
||||||
{
|
{
|
||||||
if (arrayList->object.fnObjectEquals(arrayList->array[index], obj))
|
if (arrayList->object.fnObjectEquals(arrayList->array[index], obj))
|
||||||
{
|
{
|
||||||
@ -392,8 +411,7 @@ int ArrayList_IndexOf(wArrayList* arrayList, void* obj, int startIndex, int coun
|
|||||||
if (!found)
|
if (!found)
|
||||||
index = -1;
|
index = -1;
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Unlock_Conditional(arrayList);
|
||||||
LeaveCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@ -411,23 +429,25 @@ int ArrayList_IndexOf(wArrayList* arrayList, void* obj, int startIndex, int coun
|
|||||||
* the specified index.
|
* the specified index.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ArrayList_LastIndexOf(wArrayList* arrayList, void* obj, int startIndex, int count)
|
SSIZE_T ArrayList_LastIndexOf(wArrayList* arrayList, const void* obj, SSIZE_T startIndex,
|
||||||
|
SSIZE_T count)
|
||||||
{
|
{
|
||||||
int index;
|
SSIZE_T index, sindex, cindex;
|
||||||
BOOL found = FALSE;
|
BOOL found = FALSE;
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Lock_Conditional(arrayList);
|
||||||
EnterCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
|
sindex = (size_t)startIndex;
|
||||||
if (startIndex < 0)
|
if (startIndex < 0)
|
||||||
startIndex = 0;
|
sindex = 0;
|
||||||
|
|
||||||
|
cindex = (size_t)count;
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
count = arrayList->size;
|
cindex = arrayList->size;
|
||||||
|
|
||||||
for (index = startIndex + count - 1; index >= startIndex; index--)
|
for (index = sindex + cindex; index > sindex; index--)
|
||||||
{
|
{
|
||||||
if (arrayList->object.fnObjectEquals(arrayList->array[index], obj))
|
if (arrayList->object.fnObjectEquals(arrayList->array[index - 1], obj))
|
||||||
{
|
{
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
break;
|
break;
|
||||||
@ -437,8 +457,7 @@ int ArrayList_LastIndexOf(wArrayList* arrayList, void* obj, int startIndex, int
|
|||||||
if (!found)
|
if (!found)
|
||||||
index = -1;
|
index = -1;
|
||||||
|
|
||||||
if (arrayList->synchronized)
|
ArrayList_Unlock_Conditional(arrayList);
|
||||||
LeaveCriticalSection(&arrayList->lock);
|
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@ -448,12 +467,45 @@ static BOOL ArrayList_DefaultCompare(const void* objA, const void* objB)
|
|||||||
return objA == objB ? TRUE : FALSE;
|
return objA == objB ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wObject* ArrayList_Object(wArrayList* arrayList)
|
||||||
|
{
|
||||||
|
if (!arrayList)
|
||||||
|
return NULL;
|
||||||
|
return &arrayList->object;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL ArrayList_ForEach(wArrayList* arrayList, ArrayList_ForEachFkt fkt, ...)
|
||||||
|
{
|
||||||
|
size_t index, count;
|
||||||
|
va_list ap;
|
||||||
|
BOOL rc = FALSE;
|
||||||
|
|
||||||
|
if (!arrayList || !fkt)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
ArrayList_Lock_Conditional(arrayList);
|
||||||
|
count = ArrayList_Count(arrayList);
|
||||||
|
va_start(ap, (void*)fkt);
|
||||||
|
for (index = 0; index < count; index++)
|
||||||
|
{
|
||||||
|
void* obj = ArrayList_GetItem(arrayList, index);
|
||||||
|
if (!fkt(obj, index, ap))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
rc = TRUE;
|
||||||
|
fail:
|
||||||
|
ArrayList_Unlock_Conditional(arrayList);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construction, Destruction
|
* Construction, Destruction
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wArrayList* ArrayList_New(BOOL synchronized)
|
wArrayList* ArrayList_New(BOOL synchronized)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
wArrayList* arrayList = NULL;
|
wArrayList* arrayList = NULL;
|
||||||
arrayList = (wArrayList*)calloc(1, sizeof(wArrayList));
|
arrayList = (wArrayList*)calloc(1, sizeof(wArrayList));
|
||||||
|
|
||||||
@ -461,18 +513,18 @@ wArrayList* ArrayList_New(BOOL synchronized)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
arrayList->synchronized = synchronized;
|
arrayList->synchronized = synchronized;
|
||||||
arrayList->capacity = 32;
|
|
||||||
arrayList->growthFactor = 2;
|
arrayList->growthFactor = 2;
|
||||||
arrayList->object.fnObjectEquals = ArrayList_DefaultCompare;
|
obj = ArrayList_Object(arrayList);
|
||||||
arrayList->array = (void**)calloc(arrayList->capacity, sizeof(void*));
|
if (!obj)
|
||||||
|
goto fail;
|
||||||
if (!arrayList->array)
|
obj->fnObjectEquals = ArrayList_DefaultCompare;
|
||||||
goto out_free;
|
if (!ArrayList_EnsureCapacity(arrayList, 32))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
InitializeCriticalSectionAndSpinCount(&arrayList->lock, 4000);
|
InitializeCriticalSectionAndSpinCount(&arrayList->lock, 4000);
|
||||||
return arrayList;
|
return arrayList;
|
||||||
out_free:
|
fail:
|
||||||
free(arrayList);
|
ArrayList_Free(arrayList);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,23 +27,46 @@
|
|||||||
|
|
||||||
#include <winpr/collections.h>
|
#include <winpr/collections.h>
|
||||||
|
|
||||||
|
struct _wBipBlock
|
||||||
|
{
|
||||||
|
size_t index;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
typedef struct _wBipBlock wBipBlock;
|
||||||
|
|
||||||
|
struct _wBipBuffer
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
BYTE* buffer;
|
||||||
|
size_t pageSize;
|
||||||
|
wBipBlock blockA;
|
||||||
|
wBipBlock blockB;
|
||||||
|
wBipBlock readR;
|
||||||
|
wBipBlock writeR;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Bip Buffer - The Circular Buffer with a Twist:
|
* The Bip Buffer - The Circular Buffer with a Twist:
|
||||||
* http://www.codeproject.com/Articles/3479/The-Bip-Buffer-The-Circular-Buffer-with-a-Twist
|
* http://www.codeproject.com/Articles/3479/The-Bip-Buffer-The-Circular-Buffer-with-a-Twist
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define BipBlock_Clear(_bbl) _bbl.index = _bbl.size = 0
|
static INLINE void BipBlock_Clear(wBipBlock* _bbl)
|
||||||
|
{
|
||||||
|
_bbl->index = _bbl->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#define BipBlock_Copy(_dst, _src) \
|
static INLINE void BipBlock_Copy(wBipBlock* _dst, const wBipBlock* _src)
|
||||||
_dst.index = _src.index; \
|
{
|
||||||
_dst.size = _src.size
|
_dst->index = _src->index;
|
||||||
|
_dst->size = _src->size;
|
||||||
|
}
|
||||||
|
|
||||||
void BipBuffer_Clear(wBipBuffer* bb)
|
void BipBuffer_Clear(wBipBuffer* bb)
|
||||||
{
|
{
|
||||||
BipBlock_Clear(bb->blockA);
|
BipBlock_Clear(&bb->blockA);
|
||||||
BipBlock_Clear(bb->blockB);
|
BipBlock_Clear(&bb->blockB);
|
||||||
BipBlock_Clear(bb->readR);
|
BipBlock_Clear(&bb->readR);
|
||||||
BipBlock_Clear(bb->writeR);
|
BipBlock_Clear(&bb->writeR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL BipBuffer_AllocBuffer(wBipBuffer* bb, size_t size)
|
static BOOL BipBuffer_AllocBuffer(wBipBuffer* bb, size_t size)
|
||||||
@ -198,7 +221,7 @@ void BipBuffer_WriteCommit(wBipBuffer* bb, size_t size)
|
|||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
BipBlock_Clear(bb->writeR);
|
BipBlock_Clear(&bb->writeR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +232,7 @@ void BipBuffer_WriteCommit(wBipBuffer* bb, size_t size)
|
|||||||
{
|
{
|
||||||
bb->blockA.index = bb->writeR.index;
|
bb->blockA.index = bb->writeR.index;
|
||||||
bb->blockA.size = size;
|
bb->blockA.size = size;
|
||||||
BipBlock_Clear(bb->writeR);
|
BipBlock_Clear(&bb->writeR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +241,7 @@ void BipBuffer_WriteCommit(wBipBuffer* bb, size_t size)
|
|||||||
else
|
else
|
||||||
bb->blockB.size += size;
|
bb->blockB.size += size;
|
||||||
|
|
||||||
BipBlock_Clear(bb->writeR);
|
BipBlock_Clear(&bb->writeR);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSIZE_T BipBuffer_Write(wBipBuffer* bb, const BYTE* data, size_t size)
|
SSIZE_T BipBuffer_Write(wBipBuffer* bb, const BYTE* data, size_t size)
|
||||||
@ -332,8 +355,8 @@ void BipBuffer_ReadCommit(wBipBuffer* bb, size_t size)
|
|||||||
|
|
||||||
if (size >= bb->blockA.size)
|
if (size >= bb->blockA.size)
|
||||||
{
|
{
|
||||||
BipBlock_Copy(bb->blockA, bb->blockB);
|
BipBlock_Copy(&bb->blockA, &bb->blockB);
|
||||||
BipBlock_Clear(bb->blockB);
|
BipBlock_Clear(&bb->blockB);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,57 @@
|
|||||||
|
|
||||||
#include <winpr/collections.h>
|
#include <winpr/collections.h>
|
||||||
|
|
||||||
|
/* WARNING: Do not access structs directly, the API will be reworked
|
||||||
|
* to make this opaque. */
|
||||||
|
struct _wBufferPoolItem
|
||||||
|
{
|
||||||
|
SSIZE_T size;
|
||||||
|
void* buffer;
|
||||||
|
};
|
||||||
|
typedef struct _wBufferPoolItem wBufferPoolItem;
|
||||||
|
|
||||||
|
/* WARNING: Do not access structs directly, the API will be reworked
|
||||||
|
* to make this opaque. */
|
||||||
|
struct _wBufferPool
|
||||||
|
{
|
||||||
|
SSIZE_T fixedSize;
|
||||||
|
DWORD alignment;
|
||||||
|
BOOL synchronized;
|
||||||
|
CRITICAL_SECTION lock;
|
||||||
|
|
||||||
|
SSIZE_T size;
|
||||||
|
SSIZE_T capacity;
|
||||||
|
void** array;
|
||||||
|
|
||||||
|
SSIZE_T aSize;
|
||||||
|
SSIZE_T aCapacity;
|
||||||
|
wBufferPoolItem* aArray;
|
||||||
|
|
||||||
|
SSIZE_T uSize;
|
||||||
|
SSIZE_T uCapacity;
|
||||||
|
wBufferPoolItem* uArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
static BOOL BufferPool_Lock(wBufferPool* pool)
|
||||||
|
{
|
||||||
|
if (!pool)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (pool->synchronized)
|
||||||
|
EnterCriticalSection(&pool->lock);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL BufferPool_Unlock(wBufferPool* pool)
|
||||||
|
{
|
||||||
|
if (!pool)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (pool->synchronized)
|
||||||
|
LeaveCriticalSection(&pool->lock);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C equivalent of the C# BufferManager Class:
|
* C equivalent of the C# BufferManager Class:
|
||||||
* http://msdn.microsoft.com/en-us/library/ms405814.aspx
|
* http://msdn.microsoft.com/en-us/library/ms405814.aspx
|
||||||
@ -41,10 +92,14 @@ static BOOL BufferPool_ShiftAvailable(wBufferPool* pool, int index, int count)
|
|||||||
if (pool->aSize + count > pool->aCapacity)
|
if (pool->aSize + count > pool->aCapacity)
|
||||||
{
|
{
|
||||||
wBufferPoolItem* newArray;
|
wBufferPoolItem* newArray;
|
||||||
int newCapacity = pool->aCapacity * 2;
|
SSIZE_T newCapacity = pool->aCapacity * 2;
|
||||||
|
|
||||||
newArray =
|
if (pool->alignment > 0)
|
||||||
(wBufferPoolItem*)realloc(pool->aArray, sizeof(wBufferPoolItem) * newCapacity);
|
newArray = (wBufferPoolItem*)_aligned_realloc(
|
||||||
|
pool->aArray, sizeof(wBufferPoolItem) * newCapacity, pool->alignment);
|
||||||
|
else
|
||||||
|
newArray =
|
||||||
|
(wBufferPoolItem*)realloc(pool->aArray, sizeof(wBufferPoolItem) * newCapacity);
|
||||||
if (!newArray)
|
if (!newArray)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
pool->aArray = newArray;
|
pool->aArray = newArray;
|
||||||
@ -70,9 +125,14 @@ static BOOL BufferPool_ShiftUsed(wBufferPool* pool, int index, int count)
|
|||||||
{
|
{
|
||||||
if (pool->uSize + count > pool->uCapacity)
|
if (pool->uSize + count > pool->uCapacity)
|
||||||
{
|
{
|
||||||
int newUCapacity = pool->uCapacity * 2;
|
SSIZE_T newUCapacity = pool->uCapacity * 2;
|
||||||
wBufferPoolItem* newUArray =
|
wBufferPoolItem* newUArray;
|
||||||
(wBufferPoolItem*)realloc(pool->uArray, sizeof(wBufferPoolItem) * newUCapacity);
|
if (pool->alignment > 0)
|
||||||
|
newUArray = (wBufferPoolItem*)_aligned_realloc(
|
||||||
|
pool->uArray, sizeof(wBufferPoolItem) * newUCapacity, pool->alignment);
|
||||||
|
else
|
||||||
|
newUArray =
|
||||||
|
(wBufferPoolItem*)realloc(pool->uArray, sizeof(wBufferPoolItem) * newUCapacity);
|
||||||
if (!newUArray)
|
if (!newUArray)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
pool->uCapacity = newUCapacity;
|
pool->uCapacity = newUCapacity;
|
||||||
@ -96,12 +156,11 @@ static BOOL BufferPool_ShiftUsed(wBufferPool* pool, int index, int count)
|
|||||||
* Get the buffer pool size
|
* Get the buffer pool size
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int BufferPool_GetPoolSize(wBufferPool* pool)
|
SSIZE_T BufferPool_GetPoolSize(wBufferPool* pool)
|
||||||
{
|
{
|
||||||
int size;
|
SSIZE_T size;
|
||||||
|
|
||||||
if (pool->synchronized)
|
BufferPool_Lock(pool);
|
||||||
EnterCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
if (pool->fixedSize)
|
if (pool->fixedSize)
|
||||||
{
|
{
|
||||||
@ -114,8 +173,7 @@ int BufferPool_GetPoolSize(wBufferPool* pool)
|
|||||||
size = pool->uSize;
|
size = pool->uSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool->synchronized)
|
BufferPool_Unlock(pool);
|
||||||
LeaveCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -124,14 +182,13 @@ int BufferPool_GetPoolSize(wBufferPool* pool)
|
|||||||
* Get the size of a pooled buffer
|
* Get the size of a pooled buffer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int BufferPool_GetBufferSize(wBufferPool* pool, void* buffer)
|
SSIZE_T BufferPool_GetBufferSize(wBufferPool* pool, const void* buffer)
|
||||||
{
|
{
|
||||||
int size = 0;
|
SSIZE_T size = 0;
|
||||||
int index = 0;
|
SSIZE_T index = 0;
|
||||||
BOOL found = FALSE;
|
BOOL found = FALSE;
|
||||||
|
|
||||||
if (pool->synchronized)
|
BufferPool_Lock(pool);
|
||||||
EnterCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
if (pool->fixedSize)
|
if (pool->fixedSize)
|
||||||
{
|
{
|
||||||
@ -154,8 +211,7 @@ int BufferPool_GetBufferSize(wBufferPool* pool, void* buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool->synchronized)
|
BufferPool_Unlock(pool);
|
||||||
LeaveCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
return (found) ? size : -1;
|
return (found) ? size : -1;
|
||||||
}
|
}
|
||||||
@ -164,17 +220,16 @@ int BufferPool_GetBufferSize(wBufferPool* pool, void* buffer)
|
|||||||
* Gets a buffer of at least the specified size from the pool.
|
* Gets a buffer of at least the specified size from the pool.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void* BufferPool_Take(wBufferPool* pool, int size)
|
void* BufferPool_Take(wBufferPool* pool, SSIZE_T size)
|
||||||
{
|
{
|
||||||
int index;
|
SSIZE_T index;
|
||||||
int maxSize;
|
SSIZE_T maxSize;
|
||||||
int maxIndex;
|
SSIZE_T maxIndex;
|
||||||
int foundIndex;
|
SSIZE_T foundIndex;
|
||||||
BOOL found = FALSE;
|
BOOL found = FALSE;
|
||||||
void* buffer = NULL;
|
void* buffer = NULL;
|
||||||
|
|
||||||
if (pool->synchronized)
|
BufferPool_Lock(pool);
|
||||||
EnterCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
if (pool->fixedSize)
|
if (pool->fixedSize)
|
||||||
{
|
{
|
||||||
@ -283,8 +338,7 @@ void* BufferPool_Take(wBufferPool* pool, int size)
|
|||||||
(pool->uSize)++;
|
(pool->uSize)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool->synchronized)
|
BufferPool_Unlock(pool);
|
||||||
LeaveCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
||||||
@ -294,8 +348,7 @@ out_error:
|
|||||||
else
|
else
|
||||||
free(buffer);
|
free(buffer);
|
||||||
out_error_no_free:
|
out_error_no_free:
|
||||||
if (pool->synchronized)
|
BufferPool_Unlock(pool);
|
||||||
LeaveCriticalSection(&pool->lock);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,12 +358,12 @@ out_error_no_free:
|
|||||||
|
|
||||||
BOOL BufferPool_Return(wBufferPool* pool, void* buffer)
|
BOOL BufferPool_Return(wBufferPool* pool, void* buffer)
|
||||||
{
|
{
|
||||||
|
BOOL rc = FALSE;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
BOOL found = FALSE;
|
BOOL found = FALSE;
|
||||||
|
|
||||||
if (pool->synchronized)
|
BufferPool_Lock(pool);
|
||||||
EnterCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
if (pool->fixedSize)
|
if (pool->fixedSize)
|
||||||
{
|
{
|
||||||
@ -369,14 +422,10 @@ BOOL BufferPool_Return(wBufferPool* pool, void* buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool->synchronized)
|
rc = TRUE;
|
||||||
LeaveCriticalSection(&pool->lock);
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
out_error:
|
out_error:
|
||||||
if (pool->synchronized)
|
BufferPool_Unlock(pool);
|
||||||
LeaveCriticalSection(&pool->lock);
|
return rc;
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -385,8 +434,7 @@ out_error:
|
|||||||
|
|
||||||
void BufferPool_Clear(wBufferPool* pool)
|
void BufferPool_Clear(wBufferPool* pool)
|
||||||
{
|
{
|
||||||
if (pool->synchronized)
|
BufferPool_Lock(pool);
|
||||||
EnterCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
if (pool->fixedSize)
|
if (pool->fixedSize)
|
||||||
{
|
{
|
||||||
@ -427,15 +475,14 @@ void BufferPool_Clear(wBufferPool* pool)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool->synchronized)
|
BufferPool_Unlock(pool);
|
||||||
LeaveCriticalSection(&pool->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construction, Destruction
|
* Construction, Destruction
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment)
|
wBufferPool* BufferPool_New(BOOL synchronized, SSIZE_T fixedSize, DWORD alignment)
|
||||||
{
|
{
|
||||||
wBufferPool* pool = NULL;
|
wBufferPool* pool = NULL;
|
||||||
|
|
||||||
@ -488,9 +535,7 @@ wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment)
|
|||||||
return pool;
|
return pool;
|
||||||
|
|
||||||
out_error:
|
out_error:
|
||||||
if (pool->synchronized)
|
BufferPool_Free(pool);
|
||||||
DeleteCriticalSection(&pool->lock);
|
|
||||||
free(pool);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,20 @@
|
|||||||
|
|
||||||
#include <winpr/collections.h>
|
#include <winpr/collections.h>
|
||||||
|
|
||||||
|
struct _wMessageQueue
|
||||||
|
{
|
||||||
|
size_t head;
|
||||||
|
size_t tail;
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
BOOL closed;
|
||||||
|
wMessage* array;
|
||||||
|
CRITICAL_SECTION lock;
|
||||||
|
HANDLE event;
|
||||||
|
|
||||||
|
wObject object;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message Queue inspired from Windows:
|
* Message Queue inspired from Windows:
|
||||||
* http://msdn.microsoft.com/en-us/library/ms632590/
|
* http://msdn.microsoft.com/en-us/library/ms632590/
|
||||||
@ -35,6 +49,13 @@
|
|||||||
* Properties
|
* Properties
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
wObject* MessageQueue_Object(wMessageQueue* queue)
|
||||||
|
{
|
||||||
|
if (!queue)
|
||||||
|
return NULL;
|
||||||
|
return &queue->object;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an event which is set when the queue is non-empty
|
* Gets an event which is set when the queue is non-empty
|
||||||
*/
|
*/
|
||||||
@ -48,7 +69,7 @@ HANDLE MessageQueue_Event(wMessageQueue* queue)
|
|||||||
* Gets the queue size
|
* Gets the queue size
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int MessageQueue_Size(wMessageQueue* queue)
|
size_t MessageQueue_Size(wMessageQueue* queue)
|
||||||
{
|
{
|
||||||
return queue->size;
|
return queue->size;
|
||||||
}
|
}
|
||||||
@ -67,29 +88,23 @@ BOOL MessageQueue_Wait(wMessageQueue* queue)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message)
|
static BOOL MessageQueue_EnsureCapacity(wMessageQueue* queue, size_t count)
|
||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
if (!queue)
|
||||||
if (!queue || !message)
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
EnterCriticalSection(&queue->lock);
|
if (queue->size + count >= queue->capacity)
|
||||||
|
|
||||||
if (queue->closed)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (queue->size == queue->capacity)
|
|
||||||
{
|
{
|
||||||
int old_capacity;
|
|
||||||
int new_capacity;
|
|
||||||
wMessage* new_arr;
|
wMessage* new_arr;
|
||||||
|
size_t old_capacity = queue->capacity;
|
||||||
|
size_t new_capacity = queue->capacity * 2;
|
||||||
|
|
||||||
old_capacity = queue->capacity;
|
if (new_capacity < queue->size + count)
|
||||||
new_capacity = queue->capacity * 2;
|
new_capacity = queue->size + count;
|
||||||
|
|
||||||
new_arr = (wMessage*)realloc(queue->array, sizeof(wMessage) * new_capacity);
|
new_arr = (wMessage*)realloc(queue->array, sizeof(wMessage) * new_capacity);
|
||||||
if (!new_arr)
|
if (!new_arr)
|
||||||
goto out;
|
return FALSE;
|
||||||
queue->array = new_arr;
|
queue->array = new_arr;
|
||||||
queue->capacity = new_capacity;
|
queue->capacity = new_capacity;
|
||||||
ZeroMemory(&(queue->array[old_capacity]), (new_capacity - old_capacity) * sizeof(wMessage));
|
ZeroMemory(&(queue->array[old_capacity]), (new_capacity - old_capacity) * sizeof(wMessage));
|
||||||
@ -102,10 +117,27 @@ BOOL MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyMemory(&(queue->array[queue->tail]), message, sizeof(wMessage));
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
message = &(queue->array[queue->tail]);
|
BOOL MessageQueue_Dispatch(wMessageQueue* queue, const wMessage* message)
|
||||||
message->time = GetTickCount64();
|
{
|
||||||
|
wMessage* dst;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
if (!queue || !message)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
EnterCriticalSection(&queue->lock);
|
||||||
|
|
||||||
|
if (queue->closed)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!MessageQueue_EnsureCapacity(queue, 1))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
dst = &(queue->array[queue->tail]);
|
||||||
|
*dst = *message;
|
||||||
|
dst->time = GetTickCount64();
|
||||||
|
|
||||||
queue->tail = (queue->tail + 1) % queue->capacity;
|
queue->tail = (queue->tail + 1) % queue->capacity;
|
||||||
queue->size++;
|
queue->size++;
|
||||||
@ -206,29 +238,23 @@ wMessageQueue* MessageQueue_New(const wObject* callback)
|
|||||||
if (!queue)
|
if (!queue)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
queue->capacity = 32;
|
|
||||||
queue->array = (wMessage*)calloc(queue->capacity, sizeof(wMessage));
|
|
||||||
if (!queue->array)
|
|
||||||
goto error_array;
|
|
||||||
|
|
||||||
if (!InitializeCriticalSectionAndSpinCount(&queue->lock, 4000))
|
if (!InitializeCriticalSectionAndSpinCount(&queue->lock, 4000))
|
||||||
goto error_spinlock;
|
goto fail;
|
||||||
|
|
||||||
|
if (!MessageQueue_EnsureCapacity(queue, 32))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
if (!queue->event)
|
if (!queue->event)
|
||||||
goto error_event;
|
goto fail;
|
||||||
|
|
||||||
if (callback)
|
if (callback)
|
||||||
queue->object = *callback;
|
queue->object = *callback;
|
||||||
|
|
||||||
return queue;
|
return queue;
|
||||||
|
|
||||||
error_event:
|
fail:
|
||||||
DeleteCriticalSection(&queue->lock);
|
MessageQueue_Free(queue);
|
||||||
error_spinlock:
|
|
||||||
free(queue->array);
|
|
||||||
error_array:
|
|
||||||
free(queue);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,6 +276,9 @@ int MessageQueue_Clear(wMessageQueue* queue)
|
|||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
|
if (!queue || !queue->event)
|
||||||
|
return -1;
|
||||||
|
|
||||||
EnterCriticalSection(&queue->lock);
|
EnterCriticalSection(&queue->lock);
|
||||||
|
|
||||||
while (queue->size > 0)
|
while (queue->size > 0)
|
||||||
|
@ -25,6 +25,16 @@
|
|||||||
|
|
||||||
#include <winpr/collections.h>
|
#include <winpr/collections.h>
|
||||||
|
|
||||||
|
struct _wObjectPool
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
void** array;
|
||||||
|
CRITICAL_SECTION lock;
|
||||||
|
wObject object;
|
||||||
|
BOOL synchronized;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C Object Pool similar to C# BufferManager Class:
|
* C Object Pool similar to C# BufferManager Class:
|
||||||
* http://msdn.microsoft.com/en-us/library/ms405814.aspx
|
* http://msdn.microsoft.com/en-us/library/ms405814.aspx
|
||||||
@ -34,6 +44,18 @@
|
|||||||
* Methods
|
* Methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void ObjectPool_Lock(wObjectPool* pool)
|
||||||
|
{
|
||||||
|
if (pool->synchronized)
|
||||||
|
EnterCriticalSection(&pool->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ObjectPool_Unlock(wObjectPool* pool)
|
||||||
|
{
|
||||||
|
if (pool->synchronized)
|
||||||
|
LeaveCriticalSection(&pool->lock);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an object from the pool.
|
* Gets an object from the pool.
|
||||||
*/
|
*/
|
||||||
@ -42,8 +64,7 @@ void* ObjectPool_Take(wObjectPool* pool)
|
|||||||
{
|
{
|
||||||
void* obj = NULL;
|
void* obj = NULL;
|
||||||
|
|
||||||
if (pool->synchronized)
|
ObjectPool_Lock(pool);
|
||||||
EnterCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
if (pool->size > 0)
|
if (pool->size > 0)
|
||||||
obj = pool->array[--(pool->size)];
|
obj = pool->array[--(pool->size)];
|
||||||
@ -57,8 +78,7 @@ void* ObjectPool_Take(wObjectPool* pool)
|
|||||||
if (pool->object.fnObjectInit)
|
if (pool->object.fnObjectInit)
|
||||||
pool->object.fnObjectInit(obj);
|
pool->object.fnObjectInit(obj);
|
||||||
|
|
||||||
if (pool->synchronized)
|
ObjectPool_Unlock(pool);
|
||||||
LeaveCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -69,8 +89,7 @@ void* ObjectPool_Take(wObjectPool* pool)
|
|||||||
|
|
||||||
void ObjectPool_Return(wObjectPool* pool, void* obj)
|
void ObjectPool_Return(wObjectPool* pool, void* obj)
|
||||||
{
|
{
|
||||||
if (pool->synchronized)
|
ObjectPool_Lock(pool);
|
||||||
EnterCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
if ((pool->size + 1) >= pool->capacity)
|
if ((pool->size + 1) >= pool->capacity)
|
||||||
{
|
{
|
||||||
@ -92,8 +111,14 @@ void ObjectPool_Return(wObjectPool* pool, void* obj)
|
|||||||
pool->object.fnObjectUninit(obj);
|
pool->object.fnObjectUninit(obj);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (pool->synchronized)
|
ObjectPool_Unlock(pool);
|
||||||
LeaveCriticalSection(&pool->lock);
|
}
|
||||||
|
|
||||||
|
wObject* ObjectPool_Object(wObjectPool* pool)
|
||||||
|
{
|
||||||
|
if (!pool)
|
||||||
|
return NULL;
|
||||||
|
return &pool->object;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,8 +127,7 @@ out:
|
|||||||
|
|
||||||
void ObjectPool_Clear(wObjectPool* pool)
|
void ObjectPool_Clear(wObjectPool* pool)
|
||||||
{
|
{
|
||||||
if (pool->synchronized)
|
ObjectPool_Lock(pool);
|
||||||
EnterCriticalSection(&pool->lock);
|
|
||||||
|
|
||||||
while (pool->size > 0)
|
while (pool->size > 0)
|
||||||
{
|
{
|
||||||
@ -113,8 +137,7 @@ void ObjectPool_Clear(wObjectPool* pool)
|
|||||||
pool->object.fnObjectFree(pool->array[pool->size]);
|
pool->object.fnObjectFree(pool->array[pool->size]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool->synchronized)
|
ObjectPool_Unlock(pool);
|
||||||
LeaveCriticalSection(&pool->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,11 +30,21 @@
|
|||||||
* http://msdn.microsoft.com/en-us/library/awbftdfh.aspx
|
* http://msdn.microsoft.com/en-us/library/awbftdfh.aspx
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct _wPubSub
|
||||||
|
{
|
||||||
|
CRITICAL_SECTION lock;
|
||||||
|
BOOL synchronized;
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
size_t count;
|
||||||
|
wEventType* events;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Properties
|
* Properties
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wEventType* PubSub_GetEventTypes(wPubSub* pubSub, int* count)
|
wEventType* PubSub_GetEventTypes(wPubSub* pubSub, size_t* count)
|
||||||
{
|
{
|
||||||
if (count)
|
if (count)
|
||||||
*count = pubSub->count;
|
*count = pubSub->count;
|
||||||
@ -48,17 +58,19 @@ wEventType* PubSub_GetEventTypes(wPubSub* pubSub, int* count)
|
|||||||
|
|
||||||
void PubSub_Lock(wPubSub* pubSub)
|
void PubSub_Lock(wPubSub* pubSub)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&pubSub->lock);
|
if (pubSub->synchronized)
|
||||||
|
EnterCriticalSection(&pubSub->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PubSub_Unlock(wPubSub* pubSub)
|
void PubSub_Unlock(wPubSub* pubSub)
|
||||||
{
|
{
|
||||||
LeaveCriticalSection(&pubSub->lock);
|
if (pubSub->synchronized)
|
||||||
|
LeaveCriticalSection(&pubSub->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
wEventType* PubSub_FindEventType(wPubSub* pubSub, const char* EventName)
|
wEventType* PubSub_FindEventType(wPubSub* pubSub, const char* EventName)
|
||||||
{
|
{
|
||||||
int index;
|
size_t index;
|
||||||
wEventType* event = NULL;
|
wEventType* event = NULL;
|
||||||
|
|
||||||
for (index = 0; index < pubSub->count; index++)
|
for (index = 0; index < pubSub->count; index++)
|
||||||
@ -73,7 +85,7 @@ wEventType* PubSub_FindEventType(wPubSub* pubSub, const char* EventName)
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, int count)
|
void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, size_t count)
|
||||||
{
|
{
|
||||||
if (pubSub->synchronized)
|
if (pubSub->synchronized)
|
||||||
PubSub_Lock(pubSub);
|
PubSub_Lock(pubSub);
|
||||||
@ -126,7 +138,7 @@ int PubSub_Subscribe(wPubSub* pubSub, const char* EventName, pEventHandler Event
|
|||||||
|
|
||||||
int PubSub_Unsubscribe(wPubSub* pubSub, const char* EventName, pEventHandler EventHandler)
|
int PubSub_Unsubscribe(wPubSub* pubSub, const char* EventName, pEventHandler EventHandler)
|
||||||
{
|
{
|
||||||
int index;
|
size_t index;
|
||||||
wEventType* event;
|
wEventType* event;
|
||||||
int status = -1;
|
int status = -1;
|
||||||
|
|
||||||
@ -195,9 +207,7 @@ int PubSub_OnEvent(wPubSub* pubSub, const char* EventName, void* context, wEvent
|
|||||||
|
|
||||||
wPubSub* PubSub_New(BOOL synchronized)
|
wPubSub* PubSub_New(BOOL synchronized)
|
||||||
{
|
{
|
||||||
wPubSub* pubSub = NULL;
|
wPubSub* pubSub = (wPubSub*)calloc(1, sizeof(wPubSub));
|
||||||
|
|
||||||
pubSub = (wPubSub*)malloc(sizeof(wPubSub));
|
|
||||||
|
|
||||||
if (!pubSub)
|
if (!pubSub)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -205,24 +215,19 @@ wPubSub* PubSub_New(BOOL synchronized)
|
|||||||
pubSub->synchronized = synchronized;
|
pubSub->synchronized = synchronized;
|
||||||
|
|
||||||
if (pubSub->synchronized && !InitializeCriticalSectionAndSpinCount(&pubSub->lock, 4000))
|
if (pubSub->synchronized && !InitializeCriticalSectionAndSpinCount(&pubSub->lock, 4000))
|
||||||
{
|
goto fail;
|
||||||
free(pubSub);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pubSub->count = 0;
|
pubSub->count = 0;
|
||||||
pubSub->size = 64;
|
pubSub->size = 64;
|
||||||
|
|
||||||
pubSub->events = (wEventType*)calloc(pubSub->size, sizeof(wEventType));
|
pubSub->events = (wEventType*)calloc(pubSub->size, sizeof(wEventType));
|
||||||
if (!pubSub->events)
|
if (!pubSub->events)
|
||||||
{
|
goto fail;
|
||||||
if (pubSub->synchronized)
|
|
||||||
DeleteCriticalSection(&pubSub->lock);
|
|
||||||
free(pubSub);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pubSub;
|
return pubSub;
|
||||||
|
fail:
|
||||||
|
PubSub_Free(pubSub);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PubSub_Free(wPubSub* pubSub)
|
void PubSub_Free(wPubSub* pubSub)
|
||||||
|
@ -25,6 +25,22 @@
|
|||||||
|
|
||||||
#include <winpr/collections.h>
|
#include <winpr/collections.h>
|
||||||
|
|
||||||
|
struct _wQueue
|
||||||
|
{
|
||||||
|
size_t capacity;
|
||||||
|
size_t growthFactor;
|
||||||
|
BOOL synchronized;
|
||||||
|
|
||||||
|
size_t head;
|
||||||
|
size_t tail;
|
||||||
|
size_t size;
|
||||||
|
void** array;
|
||||||
|
CRITICAL_SECTION lock;
|
||||||
|
HANDLE event;
|
||||||
|
|
||||||
|
wObject object;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C equivalent of the C# Queue Class:
|
* C equivalent of the C# Queue Class:
|
||||||
* http://msdn.microsoft.com/en-us/library/system.collections.queue.aspx
|
* http://msdn.microsoft.com/en-us/library/system.collections.queue.aspx
|
||||||
@ -40,15 +56,13 @@
|
|||||||
|
|
||||||
int Queue_Count(wQueue* queue)
|
int Queue_Count(wQueue* queue)
|
||||||
{
|
{
|
||||||
int ret;
|
size_t ret;
|
||||||
|
|
||||||
if (queue->synchronized)
|
Queue_Lock(queue);
|
||||||
EnterCriticalSection(&queue->lock);
|
|
||||||
|
|
||||||
ret = queue->size;
|
ret = queue->size;
|
||||||
|
|
||||||
if (queue->synchronized)
|
Queue_Unlock(queue);
|
||||||
LeaveCriticalSection(&queue->lock);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -59,7 +73,8 @@ int Queue_Count(wQueue* queue)
|
|||||||
|
|
||||||
void Queue_Lock(wQueue* queue)
|
void Queue_Lock(wQueue* queue)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&queue->lock);
|
if (queue->synchronized)
|
||||||
|
EnterCriticalSection(&queue->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,7 +83,8 @@ void Queue_Lock(wQueue* queue)
|
|||||||
|
|
||||||
void Queue_Unlock(wQueue* queue)
|
void Queue_Unlock(wQueue* queue)
|
||||||
{
|
{
|
||||||
LeaveCriticalSection(&queue->lock);
|
if (queue->synchronized)
|
||||||
|
LeaveCriticalSection(&queue->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,6 +96,13 @@ HANDLE Queue_Event(wQueue* queue)
|
|||||||
return queue->event;
|
return queue->event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wObject* Queue_Object(wQueue* queue)
|
||||||
|
{
|
||||||
|
if (!queue)
|
||||||
|
return NULL;
|
||||||
|
return &queue->object;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Methods
|
* Methods
|
||||||
*/
|
*/
|
||||||
@ -90,10 +113,9 @@ HANDLE Queue_Event(wQueue* queue)
|
|||||||
|
|
||||||
void Queue_Clear(wQueue* queue)
|
void Queue_Clear(wQueue* queue)
|
||||||
{
|
{
|
||||||
int index;
|
size_t index;
|
||||||
|
|
||||||
if (queue->synchronized)
|
Queue_Lock(queue);
|
||||||
EnterCriticalSection(&queue->lock);
|
|
||||||
|
|
||||||
for (index = queue->head; index != queue->tail; index = (index + 1) % queue->capacity)
|
for (index = queue->head; index != queue->tail; index = (index + 1) % queue->capacity)
|
||||||
{
|
{
|
||||||
@ -106,21 +128,19 @@ void Queue_Clear(wQueue* queue)
|
|||||||
queue->size = 0;
|
queue->size = 0;
|
||||||
queue->head = queue->tail = 0;
|
queue->head = queue->tail = 0;
|
||||||
ResetEvent(queue->event);
|
ResetEvent(queue->event);
|
||||||
if (queue->synchronized)
|
Queue_Unlock(queue);
|
||||||
LeaveCriticalSection(&queue->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether an element is in the Queue.
|
* Determines whether an element is in the Queue.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL Queue_Contains(wQueue* queue, void* obj)
|
BOOL Queue_Contains(wQueue* queue, const void* obj)
|
||||||
{
|
{
|
||||||
int index;
|
size_t index;
|
||||||
BOOL found = FALSE;
|
BOOL found = FALSE;
|
||||||
|
|
||||||
if (queue->synchronized)
|
Queue_Lock(queue);
|
||||||
EnterCriticalSection(&queue->lock);
|
|
||||||
|
|
||||||
for (index = 0; index < queue->tail; index++)
|
for (index = 0; index < queue->tail; index++)
|
||||||
{
|
{
|
||||||
@ -131,37 +151,27 @@ BOOL Queue_Contains(wQueue* queue, void* obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queue->synchronized)
|
Queue_Unlock(queue);
|
||||||
LeaveCriticalSection(&queue->lock);
|
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static BOOL Queue_EnsureCapacity(wQueue* queue, size_t count)
|
||||||
* Adds an object to the end of the Queue.
|
|
||||||
*/
|
|
||||||
|
|
||||||
BOOL Queue_Enqueue(wQueue* queue, void* obj)
|
|
||||||
{
|
{
|
||||||
BOOL ret = TRUE;
|
if (!queue)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (queue->synchronized)
|
if (queue->size + count >= queue->capacity)
|
||||||
EnterCriticalSection(&queue->lock);
|
|
||||||
|
|
||||||
if (queue->size == queue->capacity)
|
|
||||||
{
|
{
|
||||||
int old_capacity;
|
const size_t old_capacity = queue->capacity;
|
||||||
int new_capacity;
|
size_t new_capacity = queue->capacity * queue->growthFactor;
|
||||||
void** newArray;
|
void** newArray;
|
||||||
old_capacity = queue->capacity;
|
if (new_capacity < queue->size + count)
|
||||||
new_capacity = queue->capacity * queue->growthFactor;
|
new_capacity = queue->size + count;
|
||||||
newArray = (void**)realloc(queue->array, sizeof(void*) * new_capacity);
|
newArray = (void**)realloc(queue->array, sizeof(void*) * new_capacity);
|
||||||
|
|
||||||
if (!newArray)
|
if (!newArray)
|
||||||
{
|
return FALSE;
|
||||||
ret = FALSE;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
queue->capacity = new_capacity;
|
queue->capacity = new_capacity;
|
||||||
queue->array = newArray;
|
queue->array = newArray;
|
||||||
@ -174,6 +184,21 @@ BOOL Queue_Enqueue(wQueue* queue, void* obj)
|
|||||||
queue->tail += old_capacity;
|
queue->tail += old_capacity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an object to the end of the Queue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL Queue_Enqueue(wQueue* queue, void* obj)
|
||||||
|
{
|
||||||
|
BOOL ret = TRUE;
|
||||||
|
|
||||||
|
Queue_Lock(queue);
|
||||||
|
|
||||||
|
if (!Queue_EnsureCapacity(queue, 1))
|
||||||
|
goto out;
|
||||||
|
|
||||||
queue->array[queue->tail] = obj;
|
queue->array[queue->tail] = obj;
|
||||||
queue->tail = (queue->tail + 1) % queue->capacity;
|
queue->tail = (queue->tail + 1) % queue->capacity;
|
||||||
@ -181,8 +206,7 @@ BOOL Queue_Enqueue(wQueue* queue, void* obj)
|
|||||||
SetEvent(queue->event);
|
SetEvent(queue->event);
|
||||||
out:
|
out:
|
||||||
|
|
||||||
if (queue->synchronized)
|
Queue_Unlock(queue);
|
||||||
LeaveCriticalSection(&queue->lock);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -195,8 +219,7 @@ void* Queue_Dequeue(wQueue* queue)
|
|||||||
{
|
{
|
||||||
void* obj = NULL;
|
void* obj = NULL;
|
||||||
|
|
||||||
if (queue->synchronized)
|
Queue_Lock(queue);
|
||||||
EnterCriticalSection(&queue->lock);
|
|
||||||
|
|
||||||
if (queue->size > 0)
|
if (queue->size > 0)
|
||||||
{
|
{
|
||||||
@ -209,8 +232,7 @@ void* Queue_Dequeue(wQueue* queue)
|
|||||||
if (queue->size < 1)
|
if (queue->size < 1)
|
||||||
ResetEvent(queue->event);
|
ResetEvent(queue->event);
|
||||||
|
|
||||||
if (queue->synchronized)
|
Queue_Unlock(queue);
|
||||||
LeaveCriticalSection(&queue->lock);
|
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -223,14 +245,12 @@ void* Queue_Peek(wQueue* queue)
|
|||||||
{
|
{
|
||||||
void* obj = NULL;
|
void* obj = NULL;
|
||||||
|
|
||||||
if (queue->synchronized)
|
Queue_Lock(queue);
|
||||||
EnterCriticalSection(&queue->lock);
|
|
||||||
|
|
||||||
if (queue->size > 0)
|
if (queue->size > 0)
|
||||||
obj = queue->array[queue->head];
|
obj = queue->array[queue->head];
|
||||||
|
|
||||||
if (queue->synchronized)
|
Queue_Unlock(queue);
|
||||||
LeaveCriticalSection(&queue->lock);
|
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -246,43 +266,40 @@ static BOOL default_queue_equals(const void* obj1, const void* obj2)
|
|||||||
|
|
||||||
wQueue* Queue_New(BOOL synchronized, int capacity, int growthFactor)
|
wQueue* Queue_New(BOOL synchronized, int capacity, int growthFactor)
|
||||||
{
|
{
|
||||||
|
wObject* obj;
|
||||||
wQueue* queue = NULL;
|
wQueue* queue = NULL;
|
||||||
queue = (wQueue*)calloc(1, sizeof(wQueue));
|
queue = (wQueue*)calloc(1, sizeof(wQueue));
|
||||||
|
|
||||||
if (!queue)
|
if (!queue)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
queue->capacity = 32;
|
|
||||||
queue->growthFactor = 2;
|
|
||||||
queue->synchronized = synchronized;
|
queue->synchronized = synchronized;
|
||||||
|
|
||||||
if (capacity > 0)
|
queue->growthFactor = 2;
|
||||||
queue->capacity = capacity;
|
|
||||||
|
|
||||||
if (growthFactor > 0)
|
if (growthFactor > 0)
|
||||||
queue->growthFactor = growthFactor;
|
queue->growthFactor = growthFactor;
|
||||||
|
|
||||||
queue->array = (void**)calloc(queue->capacity, sizeof(void*));
|
if (capacity <= 0)
|
||||||
|
capacity = 32;
|
||||||
if (!queue->array)
|
if (!Queue_EnsureCapacity(queue, capacity))
|
||||||
goto out_free;
|
goto fail;
|
||||||
|
|
||||||
queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
|
||||||
if (!queue->event)
|
if (!queue->event)
|
||||||
goto out_free_array;
|
goto fail;
|
||||||
|
|
||||||
if (!InitializeCriticalSectionAndSpinCount(&queue->lock, 4000))
|
if (!InitializeCriticalSectionAndSpinCount(&queue->lock, 4000))
|
||||||
goto out_free_event;
|
goto fail;
|
||||||
|
|
||||||
|
obj = Queue_Object(queue);
|
||||||
|
if (!obj)
|
||||||
|
goto fail;
|
||||||
|
obj->fnObjectEquals = default_queue_equals;
|
||||||
|
|
||||||
queue->object.fnObjectEquals = default_queue_equals;
|
|
||||||
return queue;
|
return queue;
|
||||||
out_free_event:
|
fail:
|
||||||
CloseHandle(queue->event);
|
Queue_Free(queue);
|
||||||
out_free_array:
|
|
||||||
free(queue->array);
|
|
||||||
out_free:
|
|
||||||
free(queue);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user