thank you very much, I understand a lot. I still have 3 questions:
1) it is a bit troublesome if I need to maintain and deal with an
additional table which cache the timeout event. The program is running
according to event loop, then WHEN can I call free() on those timer events?
If I can free the event inside the callback function, then it is much more
convenient, is it possible? like:
evtimer_set(&pkt_ev, timer_cb, &pkt_ev);
event_base_set(base, &pkt_ev);
event_add(&pkt_ev, timeout);
the callback function timer_cb():
timer_cb(int fd, short ev, void* arg){
if(...) delete(table, pkt);
.......
*free(arg); * // here the arg is &pkt_ev
}
my initial thinking is: after the callback function timer_cb() is called,
the libevent will implicitly call event_del(&pkt_ev). But I freed
&pkt_ev inside
the callback, there will be a crash/exception on event_del(&pkt_ev). is it
right?
but if event_del(&pkt_ev) doesn't care what content pkt_ev points to, it
might not be a problem?
2) why do you use the following line to set every byte of the event to 1,
is there any special reason?
struct event *pkt_ev = calloc(1,
sizeof(*pkt_ev));
3) Still I'm not clear on the event_init() function.
according to your explanation and my understanding, when this function
event_init() is called as below, libevent will create 2 event bases, the
default base(global)and mybase(local variable), if I don't explicitly bind
an event to mybase, it will be bound to the default base.
is my understanding correct?
struct event_base * mybase = event_init();
thank you!
2013/5/22 Nir Soffer <[email protected]>
>
> I cannot help you with libevent 1.4 (I would use libevent 2 for new
> project). However, for creating events, you cannot use the stack.
>
> The simplest solution would be to malloc a new event structure when you
> need a new event. You will have to free the event structure after you
> remove the event from the event loop.
>
> For example:
>
> struct event *pkt_ev = calloc(1, sizeof(*pkt_ev));
>
> // Configure and add the event to the event loop...
>
> // When you are done
> free(pkt_ev);
>
> You will probbaly need to keep the pointer to the event, so you can cancel
> the timer when you finished with the operation that needs a timeout. For
> example, maybe you want to create a struct that hold a packet and an event,
> and keep a table of these.
>
> struct pkt_ctx {
> struct pkt pkt;
> struct event timeout;
> };
>
> On Wed, May 22, 2013 at 10:41 AM, wen lui <[email protected]> wrote:
>
>>
>> *MY special case:*:
>>
>> in the main.c
>>
>> int main(){
>> struct event_base *base;
>> struct event pcap_ev;
>> ..... // here I get a file
>> descriptor pcapfd
>> event_set(&pcap_ev, pcapfd, EV_READ|EV_PERSIST,
>> on_capture, pcap_handle);
>> event_base_set(base, &pcap_ev);
>> event_add(&pcap_ev, NULL);
>> .....
>> event_base_dispatch(base);
>> }
>>
>> on_capture callback function:
>> void *on_capture(int pcapfd, short op, void *arg)
>> {
>> pcap_t *handle;
>> handle = (pcap_t *)arg;
>> fqueue_t* pkt_queue;
>>
>> pkt_queue = init_fqueue();
>> pcap_dispatch(handle, -1, collect_pkt, pkt_queue); // this
>> function put all the cached packets into pkt_queue
>> process_pcap(pkt_queue);
>> }
>>
>> the sub-routine process_pcap():
>>
>> void process_pcap(pkt_queue);{
>> for (pkt in pkt_queue){ // here is pseudo code
>> insert(table, pkt); // here insert the pkt
>> into a certain table
>> struct event pkt_ev;
>> evtimer_set(&pkt_ev, timer_cb, NULL); // I want
>> to call timer_cb after timeout
>> event_base_set(base, &pkt_ev);
>> event_add(&pkt_ev, timeout);
>> }
>> }
>>
>> the callback function timer_cb():
>>
>> timer_cb(...){
>> if(...) delete(table, pkt);
>> .......
>> }
>>
>>
>> I'm just afraid timer_cb() won't be called because pkt_ev is a local
>> variable.
>>
>>
>>
>> 2013/5/22 wen lui <[email protected]>
>>
>>>
>>>
>>> void func(){
>>> struct event ev1;
>>>
>>> event_set(&ev1, ...);
>>> event_base_set(base, &ev);
>>>
>>>
>>> event_add(&ev1, ...)
>>> }
>>>
>>> int main(){
>>> struct event_base * mybase = event_init();
>>>
>>>
>>> func();
>>> event_base_dispatch(base);
>>> }
>>>
>>>
>>> -----------------------------------------------------------------------------------------------------------------
>>> the more complete version is as above. you mean the event_init() will
>>> create 2 event bases, the default base
>>> and mybase? why will the memory used for the event be overwritten by
>>> random data if it is added to the
>>> default base? if it is added to mybase, there is no problem?
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> Basically what you want to do is:
>>>
>>> - Create new events when needed with event_new()
>>> - Add the new events to base with event_add()
>>> - Free your events when done with event_free()
>>>
>>> --------------------------------------------------------------------------------------------------------------
>>> event_new() is in libevent version 2.0.xxx, I'm using libevent version
>>> 1.4xxxx
>>> I think the following 3 lines can replace event_new()
>>>
>>> struct event ev1;
>>> event_set(&ev1, ...);
>>> event_base_set(base, &ev);
>>>
>>>
>>>
>>>
>>> I'm just afraid, if the event is created in a non-main sub-routine, then it
>>> is
>>>
>>>
>>> a local variable. its lifetime is inside that sub-routine. When event_add()
>>> is
>>> called in that sub-routine, the event is added to event loop, but after that
>>>
>>>
>>>
>>> subroutine is finished, the local variable is game over. If libevent
>>> doesn't make
>>> a copy of the event inside the event loop, there is a crash.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> 2013/5/22 Nir Soffer <[email protected]>
>>>
>>>> On Wed, May 22, 2013 at 4:41 AM, wen lui <[email protected]>wrote:
>>>>
>>>>> From stackoverflow I get to know that if I define a struct event
>>>>> variable in a function which is different from where
>>>>> event_base_dispatch()
>>>>> is defined, this event will not be added to the event loop, as below,
>>>>> ev1 will not be added to event loop.
>>>>>
>>>>> void func(){
>>>>> struct event ev1;
>>>>>
>>>>>
>>>> This event is on the stuck...
>>>>
>>>>
>>>>>
>>>>> event_set(&ev1, ...);
>>>>> event_add(&ev1, ...)
>>>>>
>>>>>
>>>> And you added it to the default event base.
>>>>
>>>> If you dispatch the default base, you probably crash (soon if you are
>>>> lucky). The memory used for the event will be overwritten by random data
>>>> when another function is called.
>>>>
>>>>
>>>>>
>>>>> }
>>>>>
>>>>> int main(){
>>>>> func();
>>>>>
>>>>>
>>>> Here you dispatch on another base.
>>>>
>>>>
>>>>>
>>>>> event_base_dispatch(base);
>>>>> }
>>>>>
>>>>> my problem is that I can't estimate the number of events in advance(think
>>>>> about discrete-event-driven simulation
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> if you know it, but I'm not using libevent for this purpose). so I have
>>>>> to create one event each time a call
>>>>> back function or its sub-function wants to insert an event into the
>>>>> event_loop. That's being said I need to create
>>>>> many events that are local varibles which are not seen by
>>>>> event_base_dispatch(base);
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> are there any workaround for my problem?
>>>>>
>>>>> No, but reading libevent book may help.
>>>> http://www.wangafu.net/~nickm/libevent-book/
>>>>
>>>> Basically what you want to do is:
>>>>
>>>> - Create new events when needed with event_new()
>>>> - Add the new events to base with event_add()
>>>> - Free your events when done with event_free()
>>>>
>>>>
>>>>
>>>
>>
>