OnOffNotifier.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
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(&notifier_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(&notifier_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 } // namespace oasys

Generated on Thu Jun 7 12:54:28 2007 for DTN Reference Implementation by  doxygen 1.5.1