pig*_*ack 5 c events event-driven-design
这是一个小小的理论问题.想象一下装满传感器的设备.现在,如果传感器x检测到某些东西,应该发生一些事情.同时,如果检测到其他东西,例如两个传感器检测到两个不同的东西,则该设备必须表现不同.
从网页设计(所以javascript)我学习了事件,例如(使用jquery)$(".x").on("click", function(){})或angularjs $scope.watch("name_of_var", function()).
是否有可能在C中复制此行为,而不使用复杂的库?
谢谢.
我假设您拥有一个嵌入式系统,可以在单独的线程中访问中断或主要事件循环,否则这是不可能的。
事件处理的基本模型如下:
#define NOEVENT 0
typedef void *(*EventHandler)(void *);
void *doNothing(void *p){/*do nothing absolutely*/ return NULL; }
typedef struct _event{
EventHandler handler;
}Event, *PEvent;
Event AllEvents[1000];
unsigned short counter = 0;
void InitEvents()
{
LOCK(AllEvents);
for(int i = 0; i < 1000; i++){
AllEvents[i].handler = doNothing;
}
UNLOCK(AllEvents);
}
void AddEvent(int EventType, EventHandler ev_handler)
{
LOCK(AllEvents);
AllEvents[EventType].handler = ev_handler;
UNLOCK(AllEvents);
}
void RemoveEvent(int EventType, EventHandler ev_handler)
{
LOCK(AllEvents);
AllEvents[EventType] = doNothing;
UNLOCK(AllEvents); /*to safeguard the event loop*/
}
/*to be run in separate thread*/
void EventLoop()
{
int event = NOEVENT;
EventHandler handler;
while(1){
while(event == NOEVENT)event=GetEvents();
handler = AllEvents[event].handler;
handler();/*perform on an event*/
}
}
Run Code Online (Sandbox Code Playgroud)
我能想到的一个系统是用户通知模型.您可能有一些东西可以处理您的传感器(例如,在其上轮询以查看是否发生了某些事情的线程).当它检测到某些东西时,任务应该引发一个机制,让外界知道:这是通知过程.
另一方面,只应通知对您的传感器感兴趣的人,因此,应在此处使用订阅方法来处理此问题.
现在,困难的部分进来.当传感器处理程序通知世界时,它不能花太多时间这样做,否则它可能会错过其他事件.因此,必须具有专用于通知过程的任务(或线程).另一方面,订户希望在接收到这样的通知事件时更新他们的一些数据.这显然是一个异步过程,因此订阅者必须为通知程序线程提供回调.
最后,你应该用时间戳标记你的事件,这样接收者就会知道他们得到的事件是否过时而且是否应该丢弃它.
最后的事情可能看起来像下面的代码:
/*
* Some data structures to begin with
*/
struct event;
struct notifier;
struct subscription;
struct notify_sched;
typedef int (*notify_cbck)(struct event *evt, void *private);
/*
*@type : a value to show the type of event
*@t : the timestamp of the event
*@value : a pointer towards the event data
*/
struct event {
int type;
struct timeval t; // the timestamp
void *value;
};
/*
* @type : the type in which the subscriber is interested
* @cb : the callback that should be run when an event occur
* @cb_data : the data to provide to the callback
* @next,prev : doubly-linked list
*/
struct subscription {
int type;
notify_cbck cb;
void *cb_data;
struct subscription *next, *prev;
};
/*
* This structure gathers the subscriptions of a given type.
* @type : the event type
* @subs : the subscription list
* @mutex : a mutex to protect the list while inserting/removing subscriptions
* @next,prev : link to other typed subscriptions
*/
struct typed_subscription {
int type;
struct subscription *subs;
mutex_t mutex;
struct typed_subscription *next, *prev;
};
/*
* @magic : the ID of the event producer
* @t_subs : the typed_subscription list
* @mutex : a mutex to protect data when (un)registering new types to the producer
* @next, prev : doubly-linked list ...
*/
struct notifier {
int magic;
struct typed_subscription *t_subs;
mutex_t mutex;
struct notifier *next, *prev;
};
/*
* @ntf : the notifiers list
* @mutex : a mutex to protect the ntf list
* @th : something to identify the task that hosts the scheduler
*/
struct notify_sched {
struct notifier *ntf;
mutex_t mutex;
pthread_t th; // I assume it's a classic pthread in this example.
};
Run Code Online (Sandbox Code Playgroud)
我现在没有时间完成我的回答,稍后我将对其进行编辑,为您提供完整的示例.但是从数据结构开始,你应该得到一些想法.希望无论如何这有点帮助.