OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.7/] [tools/] [src/] [librlink/] [ReventLoop.cpp] - Blame information for rev 36

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 31 wfjm
// $Id: ReventLoop.cpp 686 2015-06-04 21:08:08Z mueller $
2 19 wfjm
//
3 30 wfjm
// Copyright 2013-2015 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4 19 wfjm
//
5
// This program is free software; you may redistribute and/or modify it under
6
// the terms of the GNU General Public License as published by the Free
7
// Software Foundation, either version 2, or at your option any later version.
8
//
9
// This program is distributed in the hope that it will be useful, but
10
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
11
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
// for complete details.
13
// 
14
// Revision History: 
15
// Date         Rev Version  Comment
16 30 wfjm
// 2015-04-04   662   1.2    BUGFIX: fix race in Stop(), add UnStop,StopPending
17 20 wfjm
// 2013-04-27   511   1.1.3  BUGFIX: logic in DoCall() fixed (loop range)
18 19 wfjm
// 2013-03-05   495   1.1.2  add exception catcher to EventLoop
19
// 2013-03-01   493   1.1.1  DoCall(): remove handler on negative return
20
// 2013-02-22   491   1.1    use new RlogFile/RlogMsg interfaces
21
// 2013-01-11   473   1.0    Initial version
22
// ---------------------------------------------------------------------------
23
 
24
/*!
25
  \file
26 31 wfjm
  \version $Id: ReventLoop.cpp 686 2015-06-04 21:08:08Z mueller $
27 19 wfjm
  \brief   Implemenation of class ReventLoop.
28
*/
29
 
30
#include <string.h>
31
#include <poll.h>
32
#include <errno.h>
33
 
34
#include "boost/bind.hpp" 
35
#include "boost/thread/locks.hpp"
36
 
37
#include "librtools/Rexception.hpp"
38
#include "librtools/RosPrintf.hpp"
39
#include "librtools/RosFill.hpp"
40
#include "librtools/RlogMsg.hpp"
41
 
42
#include "ReventLoop.hpp"
43
 
44
using namespace std;
45
 
46
/*!
47
  \class Retro::ReventLoop
48
  \brief FIXME_docs
49
*/
50
 
51
// all method definitions in namespace Retro
52
namespace Retro {
53
 
54
//------------------------------------------+-----------------------------------
55
//! FIXME_docs
56
 
57
ReventLoop::ReventLoop()
58 30 wfjm
  : fStopPending(false),
59 19 wfjm
    fUpdatePoll(false),
60
    fPollDscMutex(),
61
    fPollDsc(),
62
    fPollFd(),
63
    fPollHdl(),
64
    fTraceLevel(0),
65
    fspLog()
66
{}
67
 
68
//------------------------------------------+-----------------------------------
69
//! FIXME_docs
70
 
71
ReventLoop::~ReventLoop()
72
{}
73
 
74
//------------------------------------------+-----------------------------------
75
//! FIXME_docs
76
 
77
// by default handlers should start with: 
78
//     if (pfd.revents & (~pfd.events)) return -1;
79
 
80
void ReventLoop::AddPollHandler(const pollhdl_t& pollhdl,
81
                                int fd, short events)
82
{
83
  boost::lock_guard<boost::mutex> lock(fPollDscMutex);
84
 
85
  for (size_t i=0; i<fPollDsc.size(); i++) {
86
    if (fPollDsc[i].fFd     == fd &&
87
        fPollDsc[i].fEvents == events) {
88
      throw Rexception("ReventLoop::AddPollHandler()",
89
                       "Bad args: duplicate handler");
90
    }
91
  }
92
 
93
  fPollDsc.push_back(PollDsc(pollhdl,fd,events));
94
  fUpdatePoll = true;
95
 
96
  if (fspLog && fTraceLevel >= 1) {
97
    RlogMsg lmsg(*fspLog, 'I');
98
    lmsg << "eloop: add handler: " << fd << "," << RosPrintf(events,"x");
99
  }
100
 
101
  return;
102
}
103
 
104
//------------------------------------------+-----------------------------------
105
//! FIXME_docs
106
 
107
void ReventLoop::RemovePollHandler(int fd, short events, bool nothrow)
108
{
109
  boost::lock_guard<boost::mutex> lock(fPollDscMutex);
110
 
111
  for (size_t i=0; i<fPollDsc.size(); i++) {
112
    if (fPollDsc[i].fFd     == fd &&
113
        fPollDsc[i].fEvents == events) {
114
      fPollDsc.erase(fPollDsc.begin()+i);
115
      fUpdatePoll = true;
116
      if (fspLog && fTraceLevel >= 1) {
117
        RlogMsg lmsg(*fspLog, 'I');
118
        lmsg << "eloop: remove handler: " << fd << "," << RosPrintf(events,"x");
119
      }
120
      return;
121
    }
122
  }
123
  if (!nothrow) throw Rexception("ReventLoop::RemovePollHandler()",
124
                                 "Bad args: unknown handler");
125
}
126
 
127
//------------------------------------------+-----------------------------------
128
//! FIXME_docs
129
 
130
bool ReventLoop::TestPollHandler(int fd, short events)
131
{
132
  boost::lock_guard<boost::mutex> lock(fPollDscMutex);
133
 
134
  for (size_t i=0; i<fPollDsc.size(); i++) {
135
    if (fPollDsc[i].fFd     == fd &&
136
        fPollDsc[i].fEvents == events) {
137
      return true;
138
    }
139
  }
140
  return false;
141
}
142
 
143
//------------------------------------------+-----------------------------------
144
//! FIXME_docs
145
 
146
void ReventLoop::RemovePollHandler(int fd)
147
{
148
  boost::lock_guard<boost::mutex> lock(fPollDscMutex);
149
 
150
  for (size_t i=0; i<fPollDsc.size(); i++) {
151
    if (fPollDsc[i].fFd == fd) {
152
      fPollDsc.erase(fPollDsc.begin()+i);
153
      fUpdatePoll = true;
154
      i--;                                  // re-probe this index
155
    }
156
  }
157
  return;
158
}
159
 
160
//------------------------------------------+-----------------------------------
161
//! FIXME_docs
162
 
163
void ReventLoop::EventLoop()
164
{
165
  fUpdatePoll = true;
166
 
167
  try {
168 30 wfjm
    while (!StopPending()) {
169 19 wfjm
      int irc = DoPoll();
170
      if (fPollFd.size() == 0) break;
171
      if (irc>0) DoCall();
172
    }
173
  } catch (exception& e) {
174
    if (fspLog) {
175
      RlogMsg lmsg(*fspLog, 'F');
176
      lmsg << "eloop: crashed with exception: " << e.what();
177
    }
178
    return;
179
  }
180
 
181
  return;
182
}
183
 
184
//------------------------------------------+-----------------------------------
185
//! FIXME_docs
186
 
187
void ReventLoop::Dump(std::ostream& os, int ind, const char* text) const
188
{
189
  RosFill bl(ind);
190
  os << bl << (text?text:"--") << "ReventLoop @ " << this << endl;
191 30 wfjm
  os << bl << "  fStopPending:    " << fStopPending << endl;
192 19 wfjm
  os << bl << "  fUpdatePoll:     " << fUpdatePoll << endl;
193
  {
194
    boost::lock_guard<boost::mutex> lock(((ReventLoop*)this)->fPollDscMutex);
195
    os << bl << "  fPollDsc.size    " << fPollDsc.size() << endl;
196
    os << bl << "  fPollFd.size     " << fPollFd.size()  << endl;
197
    os << bl << "  fPollHdl.size    " << fPollHdl.size() << endl;
198
    for (size_t i=0; i<fPollDsc.size(); i++) {
199
      os << bl << "    [" << RosPrintf(i,"d",3) << "]:"
200
         << " fd:" << RosPrintf(fPollDsc[i].fFd,"d",3)
201
         << " evt:" << RosPrintf(fPollDsc[i].fEvents,"x",2)
202
         << " hdl:" << (bool)fPollDsc[i].fHandler
203
         << endl;
204
    }
205
  }
206
  os << bl << "  fTraveLevel:     " << fTraceLevel << endl;
207
  os << bl << "  fspLog:          " << fspLog.get() << endl;
208
 
209
  return;
210
}
211
 
212
//------------------------------------------+-----------------------------------
213
//! FIXME_docs
214
 
215
int ReventLoop::DoPoll(int timeout)
216
{
217
  if (fUpdatePoll) {
218
    boost::lock_guard<boost::mutex> lock(fPollDscMutex);
219
 
220
    fPollFd.resize(fPollDsc.size());
221
    fPollHdl.resize(fPollDsc.size());
222
    for (size_t i=0; i<fPollDsc.size(); i++) {
223
      fPollFd[i].fd      = fPollDsc[i].fFd;
224
      fPollFd[i].events  = fPollDsc[i].fEvents;
225
      fPollFd[i].revents = 0;
226
      fPollHdl[i] = fPollDsc[i].fHandler;
227
    }
228
    fUpdatePoll = false;
229
 
230
    if (fspLog && fTraceLevel >= 1) {
231
      RlogMsg lmsg(*fspLog, 'I');
232 20 wfjm
      lmsg << "eloop: redo pollfd list, size=" << fPollDsc.size() << endl;
233 19 wfjm
    }
234
  }
235
 
236
  if (fPollFd.size() == 0) return 0;
237
 
238
  int irc = poll(fPollFd.data(), fPollFd.size(), timeout);
239
  if (irc < 0 && errno == EINTR) return 0;
240
  if (irc < 0)
241
    throw Rexception("ReventLoop::EventLoop()", "poll() failed: ", errno);
242
 
243
  if (fspLog && fTraceLevel >= 2) {
244
    RlogMsg lmsg(*fspLog, 'I');
245 31 wfjm
    lmsg << "eloop: poll(): rc=" << irc;
246 19 wfjm
    for (size_t i=0; i<fPollFd.size(); i++) {
247
      if (fPollFd[i].revents == 0) continue;
248
      lmsg << " (" << fPollFd[i].fd
249
           << "," << RosPrintf(fPollFd[i].events,"x")
250
           << "," << RosPrintf(fPollFd[i].revents,"x") << ")";
251
    }
252
  }
253
 
254
  return irc;
255
}
256
 
257
//------------------------------------------+-----------------------------------
258
//! FIXME_docs
259
 
260
void ReventLoop::DoCall(void)
261
{
262 20 wfjm
  for (size_t i=0; i<fPollFd.size(); i++) {
263
    if (fPollFd[i].revents) {
264 19 wfjm
      int irc = fPollHdl[i](fPollFd[i]);
265
      // remove handler negative return (nothrow=true to prevent remove race)
266
      if (irc < 0) {
267
        if (fspLog && fTraceLevel >= 1) {
268
          RlogMsg lmsg(*fspLog, 'I');
269
          lmsg << "eloop: handler(" << fPollFd[i].fd
270
               << "," << RosPrintf(fPollFd[i].events,"x")
271
               << ") got " << RosPrintf(fPollFd[i].revents,"x")
272
               << " and requested removal";
273
        }
274
        RemovePollHandler(fPollFd[i].fd, fPollFd[i].events, true);
275
      }
276
    }
277
  }
278
  return;
279
}
280
 
281
} // end namespace Retro

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.