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 19

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

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

powered by: WebSVN 2.1.0

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