OnOffNotifier.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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(&notifier_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(&notifier_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 } // namespace oasys

Generated on Fri Dec 22 14:48:00 2006 for DTN Reference Implementation by  doxygen 1.5.1