microbit: Added C++ member function callback support into MicroBitMessageBus
Event callbacks can now be transparently added to any C++ member function matching the MicroBitMessageBud signature: void fn(MicroBitEvent e)
This commit is contained in:
parent
8e1a15c79f
commit
8ea2e953c8
8 changed files with 367 additions and 92 deletions
77
inc/MemberFunctionCallback.h
Normal file
77
inc/MemberFunctionCallback.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
#ifndef MEMBER_FUNCTION_CALLBACK_H
|
||||
#define MEMBER_FUNCTION_CALLBACK_H
|
||||
|
||||
#include "mbed.h"
|
||||
#include "MicroBitEvent.h"
|
||||
|
||||
/**
|
||||
* Class definition for a MemberFunctionCallback.
|
||||
*
|
||||
* C++ member functions (also known as methods) have a more complex
|
||||
* representation than normal C functions. This allows a referene to
|
||||
* a C++ member function to be stored then called at a later date.
|
||||
*
|
||||
* This class is used extensively by the MicroBitMessageBus to deliver
|
||||
* events to C++ methods.
|
||||
*/
|
||||
class MemberFunctionCallback
|
||||
{
|
||||
private:
|
||||
void* object;
|
||||
uint32_t method[4];
|
||||
void (*invoke)(void *object, uint32_t *method, MicroBitEvent e);
|
||||
template <typename T> static void methodCall(void* object, uint32_t*method, MicroBitEvent e);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor. Creates a MemberFunctionCallback based on a pointer to given method.
|
||||
* @param object The object the callback method should be invooked on.
|
||||
* @param method The method to invoke.
|
||||
*/
|
||||
template <typename T> MemberFunctionCallback(T* object, void (T::*method)(MicroBitEvent e));
|
||||
|
||||
/**
|
||||
* Comparison of two MemberFunctionCallback objects.
|
||||
* @return TRUE if the given MemberFunctionCallback is equivalent to this one. FALSE otherwise.
|
||||
*/
|
||||
bool operator==(const MemberFunctionCallback &mfc);
|
||||
|
||||
/**
|
||||
* Calls the method reference held by this MemberFunctionCallback.
|
||||
* @param e The event to deliver to the method
|
||||
*/
|
||||
void fire(MicroBitEvent e);
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor. Creates a representation of a pointer to a C++ member function (method).
|
||||
* @param object The object the callback method should be invooked on.
|
||||
* @param method The method to invoke.
|
||||
*/
|
||||
template <typename T>
|
||||
MemberFunctionCallback::MemberFunctionCallback(T* object, void (T::*method)(MicroBitEvent e))
|
||||
{
|
||||
this->object = object;
|
||||
memclr(this->method, sizeof(method));
|
||||
memcpy(this->method, &method, sizeof(method));
|
||||
invoke = &MemberFunctionCallback::methodCall<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template to create static methods capable of invoking a C++ member function (method)
|
||||
* based on the given paramters.
|
||||
*/
|
||||
template <typename T>
|
||||
void MemberFunctionCallback::methodCall(void *object, uint32_t *method, MicroBitEvent e)
|
||||
{
|
||||
T* o = (T*)object;
|
||||
void (T::*m)(MicroBitEvent);
|
||||
memcpy(&m, method, sizeof(m));
|
||||
|
||||
(o->*m)(e);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -4,10 +4,6 @@
|
|||
#include "mbed.h"
|
||||
#include "MicroBitConfig.h"
|
||||
#include "MicroBitPanic.h"
|
||||
|
||||
#include "ble/BLE.h"
|
||||
#include "ble/services/DeviceInformationService.h"
|
||||
|
||||
#include "ErrorNo.h"
|
||||
|
||||
#include "MicroBitHeapAllocator.h"
|
||||
|
@ -15,9 +11,10 @@
|
|||
#include "MicroBitFiber.h"
|
||||
#include "ManagedType.h"
|
||||
#include "ManagedString.h"
|
||||
|
||||
#include "MicroBitEvent.h"
|
||||
#include "MicroBitFont.h"
|
||||
#include "MicroBitImage.h"
|
||||
#include "MicroBitEvent.h"
|
||||
#include "MicroBitMessageBus.h"
|
||||
#include "DynamicPwm.h"
|
||||
#include "MicroBitComponent.h"
|
||||
|
@ -31,6 +28,8 @@
|
|||
#include "MicroBitCompass.h"
|
||||
#include "MicroBitAccelerometer.h"
|
||||
|
||||
#include "ble/BLE.h"
|
||||
#include "ble/services/DeviceInformationService.h"
|
||||
#include "MicroBitDFUService.h"
|
||||
#include "MicroBitEventService.h"
|
||||
#include "ExternalEvents.h"
|
||||
|
|
81
inc/MicroBitListener.h
Normal file
81
inc/MicroBitListener.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
#ifndef MICROBIT_LISTENER_H
|
||||
#define MICROBIT_LISTENER_H
|
||||
|
||||
#include "mbed.h"
|
||||
#include "MicroBitEvent.h"
|
||||
|
||||
// MessageBusListener flags...
|
||||
#define MESSAGE_BUS_LISTENER_PARAMETERISED 0x0001
|
||||
#define MESSAGE_BUS_LISTENER_METHOD 0x0002
|
||||
#define MESSAGE_BUS_LISTENER_REENTRANT 0x0004
|
||||
#define MESSAGE_BUS_LISTENER_BUSY 0x0008
|
||||
|
||||
struct MicroBitListener
|
||||
{
|
||||
uint16_t id; // The ID of the component that this listener is interested in.
|
||||
uint16_t value; // Value this listener is interested in receiving.
|
||||
uint16_t flags; // Status and configuration options codes for this listener.
|
||||
|
||||
union
|
||||
{
|
||||
void (*cb)(MicroBitEvent);
|
||||
void (*cb_param)(MicroBitEvent, void *);
|
||||
MemberFunctionCallback *cb_method;
|
||||
};
|
||||
|
||||
void* cb_arg; // Optional argument to be passed to the caller.
|
||||
|
||||
MicroBitEvent evt;
|
||||
|
||||
MicroBitListener *next;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a new Message Bus Listener.
|
||||
* @param id The ID of the component you want to listen to.
|
||||
* @param value The event ID you would like to listen to from that component
|
||||
* @param handler A function pointer to call when the event is detected.
|
||||
*/
|
||||
MicroBitListener(uint16_t id, uint16_t value, void (*handler)(MicroBitEvent));
|
||||
|
||||
/**
|
||||
* Alternative constructor where we register a value to be passed to the
|
||||
* callback.
|
||||
*/
|
||||
MicroBitListener(uint16_t id, uint16_t value, void (*handler)(MicroBitEvent, void *), void* arg);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a new Message Bus Listener, with a callback to a c++ member function.
|
||||
* @param id The ID of the component you want to listen to.
|
||||
* @param value The event ID you would like to listen to from that component.
|
||||
* @param object The C++ object on which to call the event handler.
|
||||
* @param object The method within the C++ object to call.
|
||||
*/
|
||||
template <typename T>
|
||||
MicroBitListener(uint16_t id, uint16_t value, T* object, void (T::*method)(MicroBitEvent));
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a new Message Bus Listener, with a callback to a c++ member function.
|
||||
* @param id The ID of the component you want to listen to.
|
||||
* @param value The event ID you would like to listen to from that component.
|
||||
* @param object The C++ object on which to call the event handler.
|
||||
* @param object The method within the C++ object to call.
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
MicroBitListener::MicroBitListener(uint16_t id, uint16_t value, T* object, void (T::*method)(MicroBitEvent))
|
||||
{
|
||||
this->id = id;
|
||||
this->value = value;
|
||||
this->cb_method = new MemberFunctionCallback(object, method);
|
||||
this->cb_arg = NULL;
|
||||
this->flags = MESSAGE_BUS_LISTENER_METHOD;
|
||||
this->next = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
#define MICROBIT_MESSAGE_BUS_H
|
||||
|
||||
#include "mbed.h"
|
||||
#include "MemberFunctionCallback.h"
|
||||
#include "MicroBitListener.h"
|
||||
#include "MicroBitComponent.h"
|
||||
#include "MicroBitEvent.h"
|
||||
|
||||
|
@ -10,33 +12,9 @@
|
|||
#define MICROBIT_ID_ANY 0
|
||||
#define MICROBIT_EVT_ANY 0
|
||||
|
||||
struct MicroBitListener
|
||||
{
|
||||
uint16_t id; // The ID of the component that this listener is interested in.
|
||||
uint16_t value; // Value this listener is interested in receiving.
|
||||
void* cb; // Callback function associated with this listener. Either (*cb)(MicroBitEvent) or (*cb)(MicroBitEvent, void*) depending on whether cb_arg is NULL.
|
||||
void* cb_arg; // Argument to be passed to the caller. This is assumed to be a pointer, so passing in NULL means that the function doesn't take an argument.
|
||||
MicroBitEvent evt;
|
||||
|
||||
MicroBitListener *next;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a new Message Bus Listener.
|
||||
* @param id The ID of the component you want to listen to.
|
||||
* @param value The event ID you would like to listen to from that component
|
||||
* @param handler A function pointer to call when the event is detected.
|
||||
*/
|
||||
MicroBitListener(uint16_t id, uint16_t value, void (*handler)(MicroBitEvent));
|
||||
|
||||
/**
|
||||
* Alternative constructor where we register a value to be passed to the
|
||||
* callback. If arg == NULL, the function takes no extra arguemnt.
|
||||
* Otherwise, the function is understood to take an extra argument.
|
||||
*/
|
||||
MicroBitListener(uint16_t id, uint16_t value, void *handler, void* arg);
|
||||
};
|
||||
|
||||
/**
|
||||
* Enclosing class to hold a chain of events.
|
||||
*/
|
||||
struct MicroBitEventQueueItem
|
||||
{
|
||||
MicroBitEvent evt;
|
||||
|
@ -50,6 +28,7 @@ struct MicroBitEventQueueItem
|
|||
MicroBitEventQueueItem(MicroBitEvent evt);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class definition for the MicroBitMessageBus.
|
||||
*
|
||||
|
@ -136,14 +115,28 @@ class MicroBitMessageBus : public MicroBitComponent
|
|||
*/
|
||||
void listen(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg);
|
||||
|
||||
/**
|
||||
* Register a listener function.
|
||||
*
|
||||
* As above, but allows callbacks into member functions within a C++ object.
|
||||
* This one is a bit more complex, but hey, that's C++ for you!
|
||||
*/
|
||||
template <typename T>
|
||||
void listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent));
|
||||
|
||||
private:
|
||||
|
||||
|
||||
/**
|
||||
* Add the given MicroBitListener to the list of event handlers, unconditionally.
|
||||
* @param listener The MicroBitListener to validate.
|
||||
* @return 1 if the listener is valid, 0 otherwise.
|
||||
*/
|
||||
int add(MicroBitListener *newListener);
|
||||
|
||||
MicroBitListener *listeners; // Chain of active listeners.
|
||||
MicroBitEventQueueItem *evt_queue_head; // Head of queued events to be processed.
|
||||
MicroBitEventQueueItem *evt_queue_tail; // Tail of queued events to be processed.
|
||||
int seq; // Sequence number. Used to invalidate cache entries.
|
||||
|
||||
void listen(int id, int value, void* handler, void* arg);
|
||||
void queueEvent(MicroBitEvent &evt);
|
||||
MicroBitEventQueueItem* dequeueEvent();
|
||||
|
||||
|
@ -151,6 +144,35 @@ class MicroBitMessageBus : public MicroBitComponent
|
|||
virtual int isIdleCallbackNeeded();
|
||||
};
|
||||
|
||||
/**
|
||||
* A registrationt function to allow C++ member funcitons (methods) to be registered as an event
|
||||
* listener.
|
||||
*
|
||||
* @param id The source of messages to listen for. Events sent from any other IDs will be filtered.
|
||||
* Use MICROBIT_ID_ANY to receive events from all components.
|
||||
*
|
||||
* @param value The value of messages to listen for. Events with any other values will be filtered.
|
||||
* Use MICROBIT_EVT_ANY to receive events of any value.
|
||||
*
|
||||
* @param object The object on which the method should be invoked.
|
||||
* @param hander The method to call when an event is received.
|
||||
*/
|
||||
template <typename T>
|
||||
void MicroBitMessageBus::listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent))
|
||||
{
|
||||
if (object == NULL || handler == NULL)
|
||||
return;
|
||||
|
||||
MicroBitListener *newListener = new MicroBitListener(id, value, object, handler);
|
||||
|
||||
if(!add(newListener))
|
||||
{
|
||||
delete newListener->cb_method;
|
||||
delete newListener;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES
|
|||
"MicroBitPin.cpp"
|
||||
"MicroBitSerial.cpp"
|
||||
"MicroBitHeapAllocator.cpp"
|
||||
"MicroBitListener.cpp"
|
||||
"MemberFunctionCallback.cpp"
|
||||
)
|
||||
|
||||
if (YOTTA_CFG_MICROBIT_CONFIGFILE)
|
||||
|
|
32
source/MemberFunctionCallback.cpp
Normal file
32
source/MemberFunctionCallback.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Class definition for a MemberFunctionCallback.
|
||||
*
|
||||
* C++ member functions (also known as methods) have a more complex
|
||||
* representation than normal C functions. This allows a referene to
|
||||
* a C++ member function to be stored then called at a later date.
|
||||
*
|
||||
* This class is used extensively by the MicroBitMessageBus to deliver
|
||||
* events to C++ methods.
|
||||
*/
|
||||
|
||||
#include "MicroBit.h"
|
||||
|
||||
/**
|
||||
* Calls the method reference held by this MemberFunctionCallback.
|
||||
* @param e The event to deliver to the method
|
||||
*/
|
||||
void MemberFunctionCallback::fire(MicroBitEvent e)
|
||||
{
|
||||
invoke(object, method, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparison of two MemberFunctionCallback objects.
|
||||
* @return TRUE if the given MemberFunctionCallback is equivalent to this one. FALSE otherwise.
|
||||
*/
|
||||
bool MemberFunctionCallback::operator==(const MemberFunctionCallback &mfc)
|
||||
{
|
||||
return (object == mfc.object && memcmp(method,mfc.method,sizeof(method))==0);
|
||||
}
|
||||
|
||||
|
45
source/MicroBitListener.cpp
Normal file
45
source/MicroBitListener.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Class definition for a MicroBitListener.
|
||||
*
|
||||
* MicroBitListener holds all the information related to a single event handler required
|
||||
* to match and fire event handlers to incoming events.
|
||||
*/
|
||||
|
||||
#include "mbed.h"
|
||||
#include "MicroBit.h"
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a new Message Bus Listener.
|
||||
* @param id The ID of the component you want to listen to.
|
||||
* @param value The event ID you would like to listen to from that component
|
||||
* @param handler A function pointer to call when the event is detected.
|
||||
*/
|
||||
MicroBitListener::MicroBitListener(uint16_t id, uint16_t value, void (*handler)(MicroBitEvent))
|
||||
{
|
||||
this->id = id;
|
||||
this->value = value;
|
||||
this->cb = handler;
|
||||
this->cb_arg = NULL;
|
||||
this->flags = 0;
|
||||
this->next = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a new parameterised Message Bus Listener.
|
||||
* @param id The ID of the component you want to listen to.
|
||||
* @param value The event ID you would like to listen to from that component.
|
||||
* @param handler A function pointer to call when the event is detected.
|
||||
* @param arg An additional argument to pass to the event handler function.
|
||||
*/
|
||||
MicroBitListener::MicroBitListener(uint16_t id, uint16_t value, void (*handler)(MicroBitEvent, void *), void* arg)
|
||||
{
|
||||
this->id = id;
|
||||
this->value = value;
|
||||
this->cb_param = handler;
|
||||
this->cb_arg = arg;
|
||||
this->flags = MESSAGE_BUS_LISTENER_PARAMETERISED;
|
||||
this->next = NULL;
|
||||
}
|
||||
|
|
@ -16,34 +16,7 @@ MicroBitEventQueueItem::MicroBitEventQueueItem(MicroBitEvent evt)
|
|||
this->evt = evt;
|
||||
this->next = NULL;
|
||||
}
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a new Message Bus Listener.
|
||||
* @param id The ID of the component you want to listen to.
|
||||
* @param value The event ID you would like to listen to from that component
|
||||
* @param handler A function pointer to call when the event is detected.
|
||||
*/
|
||||
MicroBitListener::MicroBitListener(uint16_t id, uint16_t value, void (*handler)(MicroBitEvent))
|
||||
{
|
||||
this->id = id;
|
||||
this->value = value;
|
||||
this->cb = (void*) handler;
|
||||
this->cb_arg = NULL;
|
||||
this->next = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* A low-level, internal version of the constructor, where the handler's type is determined
|
||||
* by the value of arg. (See MicroBitMessageBus.h).
|
||||
*/
|
||||
MicroBitListener::MicroBitListener(uint16_t id, uint16_t value, void* handler, void* arg)
|
||||
{
|
||||
this->id = id;
|
||||
this->value = value;
|
||||
this->cb = handler;
|
||||
this->cb_arg = arg;
|
||||
this->next = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -65,10 +38,21 @@ MicroBitMessageBus::MicroBitMessageBus()
|
|||
void async_callback(void *param)
|
||||
{
|
||||
MicroBitListener *listener = (MicroBitListener *)param;
|
||||
if (listener->cb_arg != NULL)
|
||||
((void (*)(MicroBitEvent, void*))listener->cb)(listener->evt, listener->cb_arg);
|
||||
|
||||
// Determine the calling convention for the callback, and invoke...
|
||||
// C++ is really bad at this! Especially as the ARM compiler is yet to support C++ 11 :-/
|
||||
|
||||
// Firstly, check for a method callback into an object.
|
||||
if (listener->flags & MESSAGE_BUS_LISTENER_METHOD)
|
||||
listener->cb_method->fire(listener->evt);
|
||||
|
||||
// Now a parameterised C function
|
||||
else if (listener->flags & MESSAGE_BUS_LISTENER_PARAMETERISED)
|
||||
listener->cb_param(listener->evt, listener->cb_arg);
|
||||
|
||||
// We must have a plain C function
|
||||
else
|
||||
((void (*)(MicroBitEvent))listener->cb)(listener->evt);
|
||||
listener->cb(listener->evt);
|
||||
}
|
||||
|
||||
|
||||
|
@ -243,8 +227,6 @@ void MicroBitMessageBus::process(MicroBitEvent evt)
|
|||
*
|
||||
* @param hander The function to call when an event is received.
|
||||
*
|
||||
* TODO: We currently don't support C++ member functions as callbacks, which we should.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* void onButtonBClick(MicroBitEvent evt)
|
||||
|
@ -255,75 +237,110 @@ void MicroBitMessageBus::process(MicroBitEvent evt)
|
|||
* @endcode
|
||||
*/
|
||||
|
||||
void MicroBitMessageBus::listen(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg) {
|
||||
this->listen(id, value, (void*) handler, arg);
|
||||
}
|
||||
|
||||
void MicroBitMessageBus::listen(int id, int value, void (*handler)(MicroBitEvent)) {
|
||||
this->listen(id, value, (void*) handler, NULL);
|
||||
}
|
||||
|
||||
void MicroBitMessageBus::listen(int id, int value, void* handler, void* arg)
|
||||
void MicroBitMessageBus::listen(int id, int value, void (*handler)(MicroBitEvent))
|
||||
{
|
||||
//handler can't be NULL!
|
||||
if (handler == NULL)
|
||||
return;
|
||||
|
||||
MicroBitListener *newListener = new MicroBitListener(id, value, handler);
|
||||
|
||||
if(!add(newListener))
|
||||
{
|
||||
delete newListener;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void MicroBitMessageBus::listen(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg)
|
||||
{
|
||||
if (handler == NULL)
|
||||
return;
|
||||
|
||||
MicroBitListener *newListener = new MicroBitListener(id, value, handler, arg);
|
||||
|
||||
if(!add(newListener))
|
||||
{
|
||||
delete newListener;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the given MicroBitListener to the list of event handlers, unconditionally.
|
||||
* @param listener The MicroBitListener to validate.
|
||||
* @return 1 if the listener is valid, 0 otherwise.
|
||||
*/
|
||||
int MicroBitMessageBus::add(MicroBitListener *newListener)
|
||||
{
|
||||
MicroBitListener *l, *p;
|
||||
int methodCallback;
|
||||
|
||||
//handler can't be NULL!
|
||||
if (newListener == NULL)
|
||||
return 0;
|
||||
|
||||
methodCallback = newListener->flags & MESSAGE_BUS_LISTENER_METHOD;
|
||||
|
||||
l = listeners;
|
||||
|
||||
// Firstly, we treat a listener as an idempotent operation. Ensure we don't already have this handler
|
||||
// registered in a that will already capture these events. If we do, silently ignore.
|
||||
while (l != NULL)
|
||||
{
|
||||
if (l->id == id && l->value == value && l->cb == handler)
|
||||
return;
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
// We always check the ID, VALUE and CB_METHOD fields.
|
||||
// If we have a callback to a method, check the cb_method class. Otherwise, the cb function point is sufficient.
|
||||
while (l != NULL)
|
||||
{
|
||||
if (l->id == newListener->id && l->value == newListener->value && (methodCallback ? *l->cb_method == *newListener->cb_method : l->cb == newListener->cb))
|
||||
return 0;
|
||||
|
||||
MicroBitListener *newListener = new MicroBitListener(id, value, handler, arg);
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
//if listeners is null - we can automatically add this listener to the list at the beginning...
|
||||
// We have a valid, new event handler. Add it to the list.
|
||||
// if listeners is null - we can automatically add this listener to the list at the beginning...
|
||||
if (listeners == NULL)
|
||||
{
|
||||
listeners = newListener;
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Maintain an ordered list of listeners.
|
||||
// Chain is held stictly in increasing order of ID (first level), then value code (second level).
|
||||
// We maintain an ordered list of listeners.
|
||||
// The chain is held stictly in increasing order of ID (first level), then value code (second level).
|
||||
// Find the correct point in the chain for this event.
|
||||
// Adding a listener is a rare occurance, so we just walk the list.
|
||||
// Adding a listener is a rare occurance, so we just walk the list...
|
||||
|
||||
p = listeners;
|
||||
l = listeners;
|
||||
|
||||
while (l != NULL && l->id < id)
|
||||
while (l != NULL && l->id < newListener->id)
|
||||
{
|
||||
p = l;
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
while (l != NULL && l->id == id && l->value < value)
|
||||
while (l != NULL && l->id == newListener->id && l->value < newListener->value)
|
||||
{
|
||||
p = l;
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
//add at front of list
|
||||
if (p == listeners && (id < p->id || (p->id == id && p->value > value)))
|
||||
if (p == listeners && (newListener->id < p->id || (p->id == newListener->id && p->value > newListener->value)))
|
||||
{
|
||||
newListener->next = p;
|
||||
|
||||
//this new listener is now the front!
|
||||
listeners = newListener;
|
||||
}
|
||||
|
||||
//add after p
|
||||
else
|
||||
{
|
||||
newListener->next = p->next;
|
||||
p->next = newListener;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue