]> git.stg.codes - stg.git/blob - projects/stargazer/eventloop.cpp
Hide or add proper copy ctor and assignement operator, initialize
[stg.git] / projects / stargazer / eventloop.cpp
1 #include <cerrno>
2 #include <cstring>
3
4 #include "stg/locker.h"
5 #include "stg/common.h"
6 #include "eventloop.h"
7
8 EVENT_LOOP::EVENT_LOOP()
9     : ACTIONS_LIST(),
10       _running(false),
11       _stopped(true),
12       _tid(),
13       _mutex(),
14       _condition()
15 {
16 pthread_mutex_init(&_mutex, NULL);
17 pthread_cond_init(&_condition, NULL);
18 }
19
20 EVENT_LOOP::~EVENT_LOOP()
21 {
22 pthread_cond_destroy(&_condition);
23 pthread_mutex_destroy(&_mutex);
24 }
25
26 bool EVENT_LOOP::Start()
27 {
28 _running = true;
29 if (pthread_create(&_tid, NULL, Run, this))
30     {
31     printfd(__FILE__, "EVENT_LOOP::Start - Failed to create thread: '%s'\n", strerror(errno));
32     return true;
33     }
34 return false;
35 }
36
37 bool EVENT_LOOP::Stop()
38 {
39 _running = false;
40 // Wake up thread
41 pthread_cond_signal(&_condition);
42 // Wait until thread exit
43 pthread_join(_tid, NULL);
44 return false;
45 }
46
47 void * EVENT_LOOP::Run(void * self)
48 {
49 EVENT_LOOP * ev = static_cast<EVENT_LOOP *>(self);
50 ev->Runner();
51 return NULL;
52 }
53
54 void EVENT_LOOP::Runner()
55 {
56 _stopped = false;
57 printfd(__FILE__, "EVENT_LOOP::Runner - Before start\n");
58 while (_running)
59     {
60         {
61         STG_LOCKER lock(&_mutex, __FILE__, __LINE__);
62         // Check for any actions...
63         if (empty())
64             {
65             // ... and sleep until new actions added
66             printfd(__FILE__, "EVENT_LOOP::Runner - Sleeping until new actions arrived\n");
67             pthread_cond_wait(&_condition, &_mutex);
68             }
69         // Check for running after wake up
70         if (!_running)
71             {
72             // Don't process any actions if stopping
73             break;
74             }
75         }
76     // Create new empty actions list
77     ACTIONS_LIST local;
78     // Fast swap with current
79     swap(local);
80     // Invoke all current actions
81     printfd(__FILE__, "EVENT_LOOP::Runner - Invoke %d actions\n", local.size());
82     local.InvokeAll();
83     }
84 printfd(__FILE__, "EVENT_LOOP::Runner - Before stop\n");
85 _stopped = true;
86 }
87
88 namespace {
89
90 pthread_mutex_t singletonMutex;
91
92 }
93
94 EVENT_LOOP & EVENT_LOOP_SINGLETON::GetInstance()
95 {
96 // Double-checking technique
97 if (!_instance)
98     {
99     STG_LOCKER lock(&singletonMutex, __FILE__, __LINE__);
100     if (!_instance)
101         {
102         CreateInstance();
103         }
104     }
105 return *_instance;
106 }
107
108 void EVENT_LOOP_SINGLETON::CreateInstance()
109 {
110 static EVENT_LOOP loop;
111 _instance = &loop;
112 }
113
114 EVENT_LOOP * EVENT_LOOP_SINGLETON::_instance = NULL;