mesos-reviews mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Alexander Rojas" <alexan...@mesosphere.io>
Subject Re: Review Request 41618: Edited defer documentation in libprocess.
Date Tue, 22 Dec 2015 10:24:39 GMT

-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
https://reviews.apache.org/r/41618/#review111592
-----------------------------------------------------------


Hey Gregg, Thanks for working on this, I really think this needs documentation. However, I
think we are going great lengths to explain relatively simple concepts. I also feel that tying
so much the concept of a `defer` to a future limits the capabilities of defer.

I feel the best way to explain these concepts goes like this:

# Dispatch

`dispatch` schedules a method for asynchronous execution. It creates an event which is added
at the back of the process event queue and will be executed once it reaches the front.

# Defer

Creates a [callable object](http://en.cppreference.com/w/cpp/concept/Callable) of type `Deferred<ReturnType(ArgsTypes...)>`
which will execute a `dispatch` operation once it gets invoked.  Example:

```c++
using namespace process;

class CountProcess : public Process<CountProcess>
{
public:
  CountProcess() : counter_(0) {}
  
  void increase() { ++counter_; }
  
private:
  unsinged int counter_;
};

int main(int argc, cha** argv)
{
  CountProcess counter;
  spawn(counter);
  
  Deferred<void()> deferred = defer(counter, &CountProcess::increase);
  
  for (int i = 0; i < 10; ++i) {
    deferred();
  }
  
  // This code is equivalent to the one above:
  for (int i = 0; i < 10; ++i) {
    dispatch(counter, &CountProcess::increase);
  }
  
  terminate(counter);
  wait(counter);

  return 0;
}
```

I allows a lot of flexibility over a dispatch, since a `Deferred` object may never be invoked,
it could be invoked multiple times or it could be invoked in a completely different execution
context. Example:

```c++
// In log.cpp
using namespace process;

class LogProcess : public Process<LogProcess>
{
public:
  LogProcess(const std::string& filePath) : logfile_(filePath) {}
  ~LogProcess() { logfile_.flush(); logfile.close(); }
  
  void log(const std::string& message) { logfile_ << message << '\n'; }
  
private:
  std:::ofstream logfile_;
};

LogProcess *logProcess;

void initLog(const std::string& filePath) 
{
  logProcess = new LogProcess(filePath);
  spawn(logProcess);
}

void terminateLog()
{
  terminate(logProcess);
  delete logProcess;
}

Deferred<void(const std::string&)> getLogger()
{
  return defer(logProcess, &LogProcess::log);
}


// in log.hpp
void initLog(const std::string& filePath);
void terminateLogger();
Deferred<void(const std::string&)> getLogger();

// in main.cpp

#include <log.hpp>

// SomeOtherClass::SomeOtherClass(std::function<void(const std::string&)> logger);

int main(int argc, cha** argv)
{
  initLog("/var/log/test.log");
  
  Deferred<void(const std::string&)> logger = getLogger();
  logger("Starting app");
  
  // SomeOtherClass has no idea of what logger
  // is or even an idea of processes.
  SomeOtherClass(logger);

  terminateLog();
  return 0;
}
```

Its power really comes by when mixed with promises and futures, since it allows to attach
a `dispatch` only when a future transitions, example:

```c++
using namespace process;

void foo()
{
  ProcessBase process;
  spawn(process);

  std::thread::id mainThreadId = std::this_thread::get_id();

  Deferred<void(int)> deferred = defer(
      process,
      [mainThreadId](int i) {
        // Invoked _asynchronously_ using `process` as the
        // execution context.
        assert(mainThreadId != std::this_thread::get_id());        
      });

  Promise<int> promise;

  promise.future().then(deferred);

  promise.future().then([mainThreadId](int i) {
    // Invoked synchronously from the execution context of
    // the thread that completes the future!
    assert(mainThreadId == std::this_thread::get_id());
  });

  // Executes both callbacks synchronously, which _dispatches_
  // the deferred lambda to run asynchronously in the execution
  // context of `process` but invokes the other lambda immediately.
  promise.set(42);

  terminate(process);
}
```


3rdparty/libprocess/README.md (lines 113 - 114)
<https://reviews.apache.org/r/41618/#comment171810>

    


- Alexander Rojas


On Dec. 22, 2015, 1 a.m., Greg Mann wrote:
> 
> -----------------------------------------------------------
> This is an automatically generated e-mail. To reply, visit:
> https://reviews.apache.org/r/41618/
> -----------------------------------------------------------
> 
> (Updated Dec. 22, 2015, 1 a.m.)
> 
> 
> Review request for mesos, Benjamin Hindman and Neil Conway.
> 
> 
> Repository: mesos
> 
> 
> Description
> -------
> 
> Edited defer documentation in libprocess.
> 
> 
> Diffs
> -----
> 
>   3rdparty/libprocess/README.md 6a47f6772bb7a74af368ed970af0f1c154a070e3 
> 
> Diff: https://reviews.apache.org/r/41618/diff/
> 
> 
> Testing
> -------
> 
> Viewed on github: https://github.com/mesosphere/mesos/tree/defer_doc_update/3rdparty/libprocess
> 
> 
> Thanks,
> 
> Greg Mann
> 
>


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message