LogCabin
Event/File.h
Go to the documentation of this file.
00001 /* Copyright (c) 2011-2014 Stanford University
00002  * Copyright (c) 2014-2015 Diego Ongaro
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
00011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 #include <mutex>
00018 
00019 #ifndef LOGCABIN_EVENT_FILE_H
00020 #define LOGCABIN_EVENT_FILE_H
00021 
00022 namespace LogCabin {
00023 namespace Event {
00024 
00025 // forward declaration
00026 class Loop;
00027 
00028 /**
00029  * A File is called by the Event::Loop when a file becomes readable or
00030  * writable. The client should inherit from this and implement the
00031  * handleFileEvent() method for when the file becomes readable or writable.
00032  *
00033  * File objects can be created from any thread, but they will always fire on
00034  * the thread running the Event::Loop.
00035  */
00036 class File {
00037   public:
00038 
00039     /**
00040      * Registers a File handler to be monitored by the Event::Loop. Once this
00041      * is constructed, the Event::Loop will call the File's event handler
00042      * appropriately.
00043      *
00044      * This object must be destroyed or disableForever() called BEFORE the File
00045      * object can be destroyed safely.
00046      *
00047      * Details: That Monitor objects have distinct lifetimes from File objects
00048      * is the key reason why they exist. The registration functionality
00049      * used to be integrated in File itself, but that posed a problem on
00050      * destruction. Suppose class MyFile derives from File. ~File() is called
00051      * after MyFile::handleFileEvent() is no longer safe to call (since MyFile
00052      * members are already destroyed). So ~File() is too late to block the
00053      * Event::Loop; it needs to happen before all this. See also
00054      * https://github.com/logcabin/logcabin/issues/82
00055      */
00056     class Monitor {
00057       public:
00058         /**
00059          * Constructor; begins monitoring events on a file.
00060          * \param eventLoop
00061          *      Event::Loop that will monitor the File object.
00062          * \param file
00063          *      The file to monitor for events.
00064          * \param fileEvents
00065          *      The files handler will be invoked when any of the events
00066          *      specified by this parameter occur (OR-ed combination of
00067          *      EPOLL_EVENTS values). If this is 0 then the file handler starts
00068          *      off inactive; it will not trigger until setEvents() has been
00069          *      called (except possibly for errors such as EPOLLHUP; these
00070          *      events are always active).
00071          */
00072         Monitor(Event::Loop& eventLoop, File& file, uint32_t fileEvents);
00073 
00074         /**
00075          * Destructor; disables monitoring the file. See disableForever().
00076          */
00077         virtual ~Monitor();
00078 
00079         /**
00080          * Stop monitoring this file. To guarantee that the event loop thread
00081          * is no longer operating on the File, this method takes an
00082          * Event::Loop::Lock internally. Once this returns, it is safe to
00083          * destroy the File object, and it is guaranteed that the event loop
00084          * thread is no longer operating on the File (unless the caller is
00085          * running in the context of the File's event handler).
00086          */
00087         void disableForever();
00088 
00089         /**
00090          * Specify the events of interest for the file.
00091          * This method is safe to call concurrently with file events
00092          * triggering and disableForever. If called outside an event handler
00093          * and no Event::Loop::Lock is taken, this may have a short delay while
00094          * active handlers continue to be called.
00095          * \param events
00096          *      Indicates the conditions under which this object should be
00097          *      invoked (OR-ed combination of EPOLL_EVENTS values). If this is
00098          *      0 then the file handler is set to inactive; it will not trigger
00099          *      until setEvents() has been called (except possibly for errors
00100          *      such as EPOLLHUP; these events are always active).
00101          */
00102         void setEvents(uint32_t events);
00103 
00104         /**
00105          * Event::Loop that will monitor the file.
00106          */
00107         Event::Loop& eventLoop;
00108 
00109       private:
00110         /**
00111          * Protects #file from concurrent access/modification.
00112          */
00113         std::mutex mutex;
00114 
00115         /**
00116          * Pointer to file being monitored, or NULL if disableForever() has
00117          * been called.
00118          */
00119         File* file;
00120 
00121         // Monitor is not copyable.
00122         Monitor(const Monitor&) = delete;
00123         Monitor& operator=(const Monitor&) = delete;
00124     };
00125 
00126     /**
00127      * Specifies who is in charge of closing the file descriptor.
00128      */
00129     enum Ownership {
00130         /**
00131          * The File destructor will close() fd.
00132          */
00133         CLOSE_ON_DESTROY,
00134         /**
00135          * The caller will be in charge of closing fd. The File destructor will
00136          * not close() fd.
00137          */
00138         CALLER_CLOSES_FD,
00139     };
00140 
00141     /**
00142      * Construct a file event handler. After this is constructed, you'll want
00143      * to create an Event::File::Monitor for it.
00144      * \param fd
00145      *      A file descriptor of a valid open file to monitor. Unless release()
00146      *      is called first, this File object will close the file descriptor
00147      *      when it is destroyed.
00148      * \param ownership
00149      *      Specifies who is in charge of closing fd. Default: this class will
00150      *      close fd in the destructor.
00151      */
00152     explicit File(int fd, Ownership ownership = CLOSE_ON_DESTROY);
00153 
00154     /**
00155      * Destructor. Closes the file descriptor if ownership is set to
00156      * CLOSE_ON_DESTROY.
00157      */
00158     virtual ~File();
00159 
00160     /**
00161      * This method is overridden by a subclass and invoked when a file event
00162      * occurs. This method will be invoked by the main event loop on
00163      * whatever thread is running the Event::Loop.
00164      *
00165      * If the event still exists when this method returns (e.g., the file is
00166      * readable but the method did not read the data), then the method will be
00167      * invoked again (unless flags such as EPOLLONESHOT or EPOLLET are used).
00168      *
00169      * \param events
00170      *      Indicates whether the file is readable or writable or both (OR'ed
00171      *      combination of EPOLL_EVENTS values).
00172      */
00173     virtual void handleFileEvent(uint32_t events) = 0;
00174 
00175     /**
00176      * The file descriptor to monitor.
00177      */
00178     const int fd;
00179 
00180     /**
00181      * See Ownership.
00182      */
00183     const Ownership ownership;
00184 
00185     // File is not copyable.
00186     File(const File&) = delete;
00187     File& operator=(const File&) = delete;
00188 };
00189 
00190 } // namespace LogCabin::Event
00191 } // namespace LogCabin
00192 
00193 #endif /* LOGCABIN_EVENT_FILE_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines