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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.6/] [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 20 wfjm
// $Id: ReventLoop.cpp 511 2013-04-27 13:51:46Z mueller $
2 19 wfjm
//
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 20 wfjm
// 2013-04-27   511   1.1.3  BUGFIX: logic in DoCall() fixed (loop range)
17 19 wfjm
// 2013-03-05   495   1.1.2  add exception catcher to EventLoop
18
// 2013-03-01   493   1.1.1  DoCall(): remove handler on negative return
19
// 2013-02-22   491   1.1    use new RlogFile/RlogMsg interfaces
20
// 2013-01-11   473   1.0    Initial version
21
// ---------------------------------------------------------------------------
22
 
23
/*!
24
  \file
25 20 wfjm
  \version $Id: ReventLoop.cpp 511 2013-04-27 13:51:46Z mueller $
26 19 wfjm
  \brief   Implemenation of class ReventLoop.
27
*/
28
 
29
#include <string.h>
30
#include <poll.h>
31
#include <errno.h>
32
 
33
#include "boost/bind.hpp" 
34
#include "boost/thread/locks.hpp"
35
 
36
#include "librtools/Rexception.hpp"
37
#include "librtools/RosPrintf.hpp"
38
#include "librtools/RosFill.hpp"
39
#include "librtools/RlogMsg.hpp"
40
 
41
#include "ReventLoop.hpp"
42
 
43
using namespace std;
44
 
45
/*!
46
  \class Retro::ReventLoop
47
  \brief FIXME_docs
48
*/
49
 
50
// all method definitions in namespace Retro
51
namespace Retro {
52
 
53
//------------------------------------------+-----------------------------------
54
//! FIXME_docs
55
 
56
ReventLoop::ReventLoop()
57
  : fLoopActive(false),
58
    fUpdatePoll(false),
59
    fPollDscMutex(),
60
    fPollDsc(),
61
    fPollFd(),
62
    fPollHdl(),
63
    fTraceLevel(0),
64
    fspLog()
65
{}
66
 
67
//------------------------------------------+-----------------------------------
68
//! FIXME_docs
69
 
70
ReventLoop::~ReventLoop()
71
{}
72
 
73
//------------------------------------------+-----------------------------------
74
//! FIXME_docs
75
 
76
// by default handlers should start with: 
77
//     if (pfd.revents & (~pfd.events)) return -1;
78
 
79
void ReventLoop::AddPollHandler(const pollhdl_t& pollhdl,
80
                                int fd, short events)
81
{
82
  boost::lock_guard<boost::mutex> lock(fPollDscMutex);
83
 
84
  for (size_t i=0; i<fPollDsc.size(); i++) {
85
    if (fPollDsc[i].fFd     == fd &&
86
        fPollDsc[i].fEvents == events) {
87
      throw Rexception("ReventLoop::AddPollHandler()",
88
                       "Bad args: duplicate handler");
89
    }
90
  }
91
 
92
  fPollDsc.push_back(PollDsc(pollhdl,fd,events));
93
  fUpdatePoll = true;
94
 
95
  if (fspLog && fTraceLevel >= 1) {
96
    RlogMsg lmsg(*fspLog, 'I');
97
    lmsg << "eloop: add handler: " << fd << "," << RosPrintf(events,"x");
98
  }
99
 
100
  return;
101
}
102
 
103
//------------------------------------------+-----------------------------------
104
//! FIXME_docs
105
 
106
void ReventLoop::RemovePollHandler(int fd, short events, bool nothrow)
107
{
108
  boost::lock_guard<boost::mutex> lock(fPollDscMutex);
109
 
110
  for (size_t i=0; i<fPollDsc.size(); i++) {
111
    if (fPollDsc[i].fFd     == fd &&
112
        fPollDsc[i].fEvents == events) {
113
      fPollDsc.erase(fPollDsc.begin()+i);
114
      fUpdatePoll = true;
115
      if (fspLog && fTraceLevel >= 1) {
116
        RlogMsg lmsg(*fspLog, 'I');
117
        lmsg << "eloop: remove handler: " << fd << "," << RosPrintf(events,"x");
118
      }
119
      return;
120
    }
121
  }
122
  if (!nothrow) throw Rexception("ReventLoop::RemovePollHandler()",
123
                                 "Bad args: unknown handler");
124
}
125
 
126
//------------------------------------------+-----------------------------------
127
//! FIXME_docs
128
 
129
bool ReventLoop::TestPollHandler(int fd, short events)
130
{
131
  boost::lock_guard<boost::mutex> lock(fPollDscMutex);
132
 
133
  for (size_t i=0; i<fPollDsc.size(); i++) {
134
    if (fPollDsc[i].fFd     == fd &&
135
        fPollDsc[i].fEvents == events) {
136
      return true;
137
    }
138
  }
139
  return false;
140
}
141
 
142
//------------------------------------------+-----------------------------------
143
//! FIXME_docs
144
 
145
void ReventLoop::RemovePollHandler(int fd)
146
{
147
  boost::lock_guard<boost::mutex> lock(fPollDscMutex);
148
 
149
  for (size_t i=0; i<fPollDsc.size(); i++) {
150
    if (fPollDsc[i].fFd == fd) {
151
      fPollDsc.erase(fPollDsc.begin()+i);
152
      fUpdatePoll = true;
153
      i--;                                  // re-probe this index
154
    }
155
  }
156
  return;
157
}
158
 
159
//------------------------------------------+-----------------------------------
160
//! FIXME_docs
161
 
162
void ReventLoop::EventLoop()
163
{
164
  fLoopActive = true;
165
  fUpdatePoll = true;
166
 
167
  try {
168
    while (fLoopActive) {
169
      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
  os << bl << "  fLoopActive:     " << fLoopActive << endl;
192
  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
    lmsg << "eloop: poll(): ";
246
    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.