00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <errno.h>
00040 #include <unistd.h>
00041 #include <sys/poll.h>
00042
00043 #include "thread/Lock.h"
00044 #include "io/IO.h"
00045
00046 #include "OnOffNotifier.h"
00047 #include "Lock.h"
00048
00049 namespace oasys {
00050
00051
00052 OnOffNotifier::OnOffNotifier(const char* logpath, bool quiet)
00053 : Logger("OnOffNotifier", (logpath == 0) ? "" : logpath),
00054 waiter_(false),
00055 quiet_(quiet),
00056 active_(false)
00057 {
00058 if (logpath == 0)
00059 {
00060 logpathf("/notifier");
00061 }
00062 else
00063 {
00064 logpath_appendf("/notifier");
00065 }
00066
00067 if (pipe(pipe_) != 0) {
00068 PANIC("can't create pipe for notifier");
00069 }
00070
00071 if (!quiet_) {
00072 log_debug("created pipe, fds: %d %d", pipe_[0], pipe_[1]);
00073 }
00074
00075 for (int n = 0; n < 2; ++n) {
00076 if (IO::set_nonblocking(pipe_[n], true, quiet ? 0 : logpath_) != 0)
00077 {
00078 PANIC("error setting fd %d to nonblocking: %s",
00079 pipe_[n], strerror(errno));
00080 }
00081 }
00082 }
00083
00084
00085 OnOffNotifier::~OnOffNotifier()
00086 {
00087 if (!quiet_)
00088 {
00089 log_debug("OnOffNotifier shutting down (closing fds %d %d)",
00090 pipe_[0],
00091 pipe_[1]);
00092 }
00093 }
00094
00095
00096 bool
00097 OnOffNotifier::wait(Lock* lock, int timeout)
00098 {
00099 notifier_lock_.lock("OnOffNotifier::wait");
00100 if (waiter_)
00101 {
00102 PANIC("OnOffNotifier doesn't support multiple waiting threads");
00103 }
00104 if (!quiet_)
00105 {
00106 log_debug("wait() on %s notifier", active_ ? "active" : "inactive");
00107 }
00108
00109 if (active_)
00110 {
00111 notifier_lock_.unlock();
00112 return true;
00113 }
00114 else
00115 {
00116 waiter_ = true;
00117
00118 notifier_lock_.unlock();
00119
00120 if (lock) {
00121 lock->unlock();
00122 }
00123 int ret = IO::poll_single(read_fd(), POLLIN, 0, timeout, 0, logpath_);
00124 if (lock) {
00125 lock->lock("OnOffNotifier::wait()");
00126 }
00127
00128 notifier_lock_.lock("OnOffNotifier::wait");
00129 waiter_ = false;
00130 notifier_lock_.unlock();
00131
00132 if (ret < 0 && ret != IOTIMEOUT)
00133 {
00134 PANIC("fatal: error return from notifier poll: %s",
00135 strerror(errno));
00136 }
00137 else if (ret == IOTIMEOUT)
00138 {
00139 if (! quiet_) {
00140 log_debug("wait() timeout");
00141 }
00142 return false;
00143 }
00144 else
00145 {
00146 if (! quiet_) {
00147 log_debug("wait() notified");
00148 }
00149 }
00150 return true;
00151 }
00152 }
00153
00154
00155 void
00156 OnOffNotifier::signal()
00157 {
00158 ScopeLock l(¬ifier_lock_, "OnOffNotifier::signal");
00159 if (active_)
00160 {
00161 return;
00162 }
00163 else
00164 {
00165 int cc = write(pipe_[1], "+", 1);
00166 ASSERT(cc == 1);
00167 active_ = true;
00168 }
00169 }
00170
00171
00172 void
00173 OnOffNotifier::clear()
00174 {
00175 ScopeLock l(¬ifier_lock_, "OnOffNotifier::clear");
00176
00177 if (active_)
00178 {
00179 char buf[2];
00180 int cc = read(pipe_[0], &buf, 1);
00181 ASSERT(cc == 1);
00182 active_ = false;
00183 }
00184 else
00185 {
00186 return;
00187 }
00188 }
00189
00190 }