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