summaryrefslogtreecommitdiffstats
path: root/libparc/parc/algol/internal_parc_Event.c
diff options
context:
space:
mode:
Diffstat (limited to 'libparc/parc/algol/internal_parc_Event.c')
-rwxr-xr-xlibparc/parc/algol/internal_parc_Event.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/libparc/parc/algol/internal_parc_Event.c b/libparc/parc/algol/internal_parc_Event.c
new file mode 100755
index 00000000..74e917bf
--- /dev/null
+++ b/libparc/parc/algol/internal_parc_Event.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ */
+#include <config.h>
+
+#include <LongBow/runtime.h>
+#include <parc/algol/parc_Memory.h>
+#include "internal_parc_Event.h"
+
+/**
+ * Current implementation based on top of libevent2
+ */
+#include <event2/event.h>
+#include <event2/bufferevent.h>
+
+void *
+internal_parc_alloc(size_t size)
+{
+ void *pointer;
+
+ pointer = parcMemory_AllocateAndClear(size);
+ return pointer;
+}
+
+void *
+internal_parc_realloc(void *pointer, size_t newSize)
+{
+ void *newPointer;
+ newPointer = parcMemory_Reallocate(pointer, newSize);
+ return newPointer;
+}
+
+// We interpose on the standard "free" interface to protect against freed memory accesses.
+void
+internal_parc_free(void *ptr)
+{
+ parcMemory_Deallocate((void **) &ptr);
+}
+
+static int _libeventInitialized = 0;
+
+void
+internal_parc_initializeLibevent(void)
+{
+ if (_libeventInitialized) {
+ return;
+ }
+ _libeventInitialized = 1;
+
+ // 0x AA BB CC XX
+ // AA = major
+ // BB = minor
+ // CC = patchlevel
+ //
+ uint32_t version = event_get_version_number();
+ trapIllegalValueIf(version < 0x02001000UL,
+ "Libevent version must be at least 2.0.16, got %s",
+ event_get_version());
+
+ // Make sure libevent uses our memory allocator.
+ // Libevent allocates an internal object the first time a base is allocated
+ // that it never releases. In order to ensure our outstanding memory counters
+ // start at zero we trigger this allocation before interposing our memory allocator.
+ //
+ // Create a scheduler event base, an event, then free both of them.
+ //
+ struct event_base *evbase = event_base_new();
+ assertNotNull(evbase, "Libevent event_base_new returned NULL");
+ struct event *event = event_new(evbase, -1, 0, NULL, NULL);
+ assertNotNull(event, "Libevent event_new returned NULL");
+ event_del(event);
+ event_base_free(evbase);
+ event_free(event);
+
+ event_set_mem_functions(internal_parc_alloc,
+ internal_parc_realloc,
+ internal_parc_free);
+}
+
+PARCEventPriority
+internal_libevent_priority_to_PARCEventPriority(short evpriority)
+{
+ PARCEventPriority priority = 0;
+ switch (evpriority) {
+ case 0: priority = PARCEventPriority_Maximum;
+ break;
+ case 1: priority = PARCEventPriority_Normal;
+ break;
+ case 2: priority = PARCEventPriority_Minimum;
+ break;
+ default:
+ assertTrue(0, "Unknown Libevent priority 0x%x\n", evpriority);
+ break;
+ }
+ return priority;
+}
+
+short
+internal_PARCEventPriority_to_libevent_priority(PARCEventPriority priority)
+{
+ short evpriority = 0;
+ switch (priority) {
+ case PARCEventPriority_Maximum: evpriority = 0;
+ break;
+ case PARCEventPriority_Normal: evpriority = 1;
+ break;
+ case PARCEventPriority_Minimum: evpriority = 2;
+ break;
+ default:
+ assertTrue(0, "Unknown PARCEventPriority 0x%x\n", evpriority);
+ break;
+ }
+ return evpriority;
+}
+
+PARCEventSchedulerDispatchType
+internal_eventloop_options_to_PARCEventSchedulerDispatchType(short evoptions)
+{
+ PARCEventSchedulerDispatchType options = 0;
+ switch (evoptions) {
+ case 0: options = PARCEventSchedulerDispatchType_Blocking;
+ break;
+ case EVLOOP_ONCE: options = PARCEventSchedulerDispatchType_LoopOnce;
+ break;
+ case EVLOOP_NONBLOCK: options = PARCEventSchedulerDispatchType_NonBlocking;
+ break;
+ default:
+ assertTrue(0, "Unknown Libevent dispatcher flag 0x%x\n", evoptions);
+ break;
+ }
+ return options;
+}
+
+short
+internal_PARCEventSchedulerDispatchType_to_eventloop_options(PARCEventSchedulerDispatchType options)
+{
+ short evoptions = 0;
+ switch (options) {
+ case PARCEventSchedulerDispatchType_Blocking: evoptions = 0;
+ break;
+ case PARCEventSchedulerDispatchType_LoopOnce: evoptions = EVLOOP_ONCE;
+ break;
+ case PARCEventSchedulerDispatchType_NonBlocking: evoptions = EVLOOP_NONBLOCK;
+ break;
+ default:
+ assertTrue(0, "Unknown PARCEventSchedulerDispatchType option 0x%x\n", evoptions);
+ break;
+ }
+ return evoptions;
+}
+
+PARCEventQueueOption
+internal_bufferevent_options_to_PARCEventQueueOption(short evflags)
+{
+ PARCEventQueueOption flags = 0;
+ if (evflags & BEV_OPT_CLOSE_ON_FREE) {
+ flags |= PARCEventQueueOption_CloseOnFree;
+ evflags &= ~BEV_OPT_CLOSE_ON_FREE;
+ }
+ if (evflags & BEV_OPT_DEFER_CALLBACKS) {
+ flags |= PARCEventQueueOption_DeferCallbacks;
+ evflags &= ~BEV_OPT_DEFER_CALLBACKS;
+ }
+ assertTrue(evflags == 0, "Unknown Libevent option flag 0x%x\n", evflags);
+ return flags;
+}
+
+short
+internal_PARCEventQueueOption_to_bufferevent_options(PARCEventQueueOption flags)
+{
+ short evflags = 0;
+ if (flags & PARCEventQueueOption_CloseOnFree) {
+ evflags |= BEV_OPT_CLOSE_ON_FREE;
+ flags &= ~PARCEventQueueOption_CloseOnFree;
+ }
+ if (flags & PARCEventQueueOption_DeferCallbacks) {
+ evflags |= BEV_OPT_DEFER_CALLBACKS;
+ flags &= ~PARCEventQueueOption_DeferCallbacks;
+ }
+ assertTrue(flags == 0, "Unknown PARCEventQueueOption flag 0x%x\n", flags);
+ return evflags;
+}
+
+PARCEventQueueEventType
+internal_bufferevent_type_to_PARCEventQueueEventType(short evtypes)
+{
+ PARCEventQueueEventType types = 0;
+ if (evtypes & BEV_EVENT_READING) {
+ types |= PARCEventQueueEventType_Reading;
+ evtypes &= ~BEV_EVENT_READING;
+ }
+ if (evtypes & BEV_EVENT_WRITING) {
+ types |= PARCEventQueueEventType_Writing;
+ evtypes &= ~BEV_EVENT_WRITING;
+ }
+ if (evtypes & BEV_EVENT_EOF) {
+ types |= PARCEventQueueEventType_EOF;
+ evtypes &= ~BEV_EVENT_EOF;
+ }
+ if (evtypes & BEV_EVENT_ERROR) {
+ types |= PARCEventQueueEventType_Error;
+ evtypes &= ~BEV_EVENT_ERROR;
+ }
+ if (evtypes & BEV_EVENT_TIMEOUT) {
+ types |= PARCEventQueueEventType_Timeout;
+ evtypes &= ~BEV_EVENT_TIMEOUT;
+ }
+ if (evtypes & BEV_EVENT_CONNECTED) {
+ types |= PARCEventQueueEventType_Connected;
+ evtypes &= ~BEV_EVENT_CONNECTED;
+ }
+ assertTrue(evtypes == 0, "Unknown Libevent type flag 0x%x\n", evtypes);
+ return types;
+}
+
+short
+internal_PARCEventQueueEventType_to_bufferevent_type(PARCEventQueueEventType types)
+{
+ short evtypes = 0;
+ if (types & PARCEventQueueEventType_Reading) {
+ evtypes |= BEV_EVENT_READING;
+ types &= ~PARCEventQueueEventType_Reading;
+ }
+ if (types & PARCEventQueueEventType_Writing) {
+ evtypes |= BEV_EVENT_WRITING;
+ types &= ~PARCEventQueueEventType_Writing;
+ }
+ if (types & PARCEventQueueEventType_EOF) {
+ evtypes |= BEV_EVENT_EOF;
+ types &= ~PARCEventQueueEventType_EOF;
+ }
+ if (types & PARCEventQueueEventType_Error) {
+ evtypes |= BEV_EVENT_ERROR;
+ types &= ~PARCEventQueueEventType_Error;
+ }
+ if (types & PARCEventQueueEventType_Timeout) {
+ evtypes |= BEV_EVENT_TIMEOUT;
+ types &= ~PARCEventQueueEventType_Timeout;
+ }
+ if (types & PARCEventQueueEventType_Connected) {
+ evtypes |= BEV_EVENT_CONNECTED;
+ types &= ~PARCEventQueueEventType_Connected;
+ }
+ assertTrue(types == 0, "Unknown PARCEventQueueEventType 0x%x\n", types);
+ return evtypes;
+}
+
+PARCEventType
+internal_libevent_type_to_PARCEventType(short evtypes)
+{
+ PARCEventType types = 0;
+ if (evtypes & EV_TIMEOUT) {
+ types |= PARCEventType_Timeout;
+ evtypes &= ~EV_TIMEOUT;
+ }
+ if (evtypes & EV_READ) {
+ types |= PARCEventType_Read;
+ evtypes &= ~EV_READ;
+ }
+ if (evtypes & EV_WRITE) {
+ types |= PARCEventType_Write;
+ evtypes &= ~EV_WRITE;
+ }
+ if (evtypes & EV_SIGNAL) {
+ types |= PARCEventType_Signal;
+ evtypes &= ~EV_SIGNAL;
+ }
+ if (evtypes & EV_PERSIST) {
+ types |= PARCEventType_Persist;
+ evtypes &= ~EV_PERSIST;
+ }
+ if (evtypes & EV_ET) {
+ types |= PARCEventType_EdgeTriggered;
+ evtypes &= ~EV_ET;
+ }
+ assertTrue(evtypes == 0, "Unknown Libevent event type 0x%x\n", evtypes);
+ return types;
+}
+
+short
+internal_PARCEventType_to_libevent_type(PARCEventType types)
+{
+ short evtypes = 0;
+ if (types & PARCEventType_Timeout) {
+ evtypes |= EV_TIMEOUT;
+ types &= ~PARCEventType_Timeout;
+ }
+ if (types & PARCEventType_Read) {
+ evtypes |= EV_READ;
+ types &= ~PARCEventType_Read;
+ }
+ if (types & PARCEventType_Write) {
+ evtypes |= EV_WRITE;
+ types &= ~PARCEventType_Write;
+ }
+ if (types & PARCEventType_Signal) {
+ evtypes |= EV_SIGNAL;
+ types &= ~PARCEventType_Signal;
+ }
+ if (types & PARCEventType_Persist) {
+ evtypes |= EV_PERSIST;
+ types &= ~PARCEventType_Persist;
+ }
+ if (types & PARCEventType_EdgeTriggered) {
+ evtypes |= EV_ET;
+ types &= ~PARCEventType_EdgeTriggered;
+ }
+ assertTrue(types == 0, "Unknown Libevent event type 0x%x\n", types);
+ return evtypes;
+}