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