Home | History | Annotate | Download | only in batching_util
      1 /* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 
     16 // PeriodicFunction will periodically call the given function with a specified
     17 // period in a background thread.  After Start() returns, the thread is
     18 // guaranteed to have started. The destruction of the class causes the
     19 // background thread to be destroyed as well.  Start() should not be called more
     20 // than once.
     21 //
     22 // PeriodicFunction runs the function as soon as any previous run both is
     23 // complete and was started more than "interval_micros" earlier.  Thus, runs are
     24 // both serialized, and normally have a period of "interval_micros" if no run
     25 // exceeds the time.
     26 //
     27 // Note that, if the function takes longer than two interval_micross to finish,
     28 // then PeriodicFunction will "skip" at least one call to the function.  For
     29 // instance, if the period is 50ms and the function starts runs at time 0 for
     30 // 150ms, then the function will immediately start executing again at time 150,
     31 // but there will be no function runs corresponding to times 50 or 100.  This is
     32 // especially important to remember when using an environment with a simulated
     33 // clock: advancing simulated time atomically over N interval_micross will not
     34 // cause the function to be called N times.
     35 //
     36 // This object is thread-safe.
     37 //
     38 // Example:
     39 //
     40 //   class Foo {
     41 //    public:
     42 //     Foo() : periodic_function_([this]() { Bar(); },
     43 //                               1000 /* 1000us == 1ms*/) {
     44 //     }
     45 //
     46 //    private:
     47 //     void Bar() { ... }
     48 //
     49 //     PeriodicFunction periodic_function_;
     50 //   };
     51 
     52 #ifndef TENSORFLOW_CORE_KERNELS_BATCHING_UTIL_PERIODIC_FUNCTION_H_
     53 #define TENSORFLOW_CORE_KERNELS_BATCHING_UTIL_PERIODIC_FUNCTION_H_
     54 
     55 #include "tensorflow/core/kernels/batching_util/periodic_function.h"
     56 
     57 #include <functional>
     58 #include <memory>
     59 #include <string>
     60 
     61 #include "tensorflow/core/lib/core/notification.h"
     62 #include "tensorflow/core/platform/env.h"
     63 #include "tensorflow/core/platform/macros.h"
     64 #include "tensorflow/core/platform/mutex.h"
     65 #include "tensorflow/core/platform/thread_annotations.h"
     66 #include "tensorflow/core/platform/types.h"
     67 
     68 namespace tensorflow {
     69 namespace serving {
     70 
     71 namespace internal {
     72 class PeriodicFunctionTestAccess;
     73 }
     74 
     75 class PeriodicFunction {
     76  public:
     77   // Provides the ability to customize several aspects of the PeriodicFunction.
     78   // Passed to constructor of PeriodicFunction.
     79   struct Options {
     80     Options() {}
     81 
     82     // Any standard thread options, such as stack size, should
     83     // be passed via "thread_options".
     84     ThreadOptions thread_options;
     85 
     86     // Specifies the thread name prefix (see the description in class
     87     // Thread).
     88     string thread_name_prefix = "periodic_function";
     89 
     90     // The environment to use. Does not take ownership, but must remain alive
     91     // for as long as the PeriodicFunction exists.
     92     Env* env = Env::Default();
     93 
     94     // Specifies the length of sleep before the first invocation of the
     95     // function.
     96     // This can be used for adding a random jitter to avoid synchronous behavior
     97     // across multiple periodic functions.
     98     int64 startup_delay_micros = 0;
     99   };
    100 
    101   // Also starts the background thread which will be calling the function.
    102   PeriodicFunction(const std::function<void()>& function, int64 interval_micros,
    103                    const Options& options = Options());
    104 
    105   ~PeriodicFunction();
    106 
    107  private:
    108   friend class internal::PeriodicFunctionTestAccess;
    109 
    110   // Notifies the background thread to stop.
    111   void NotifyStop();
    112 
    113   // (Blocking.) Loops forever calling "function_" every "interval_micros_".
    114   void RunLoop(int64 start) LOCKS_EXCLUDED(mutex_);
    115 
    116   const std::function<void()> function_;  // Actual client function
    117   const int64 interval_micros_;           // Interval between calls.
    118   const Options options_;
    119 
    120   // Protects state below.
    121   mutable mutex mutex_;
    122   // Used to notify the thread to stop.
    123   Notification stop_thread_;
    124 
    125   // Thread for running "function_"
    126   std::unique_ptr<Thread> thread_ GUARDED_BY(mutex_) = nullptr;
    127 
    128   TF_DISALLOW_COPY_AND_ASSIGN(PeriodicFunction);
    129 };
    130 
    131 }  // namespace serving
    132 }  // namespace tensorflow
    133 
    134 #endif  // TENSORFLOW_CORE_KERNELS_BATCHING_UTIL_PERIODIC_FUNCTION_H_
    135