ngryman/ribs

View on GitHub
src/operation.h

Summary

Maintainability
Test Coverage
/*!
 * ribs
 * Copyright (c) 2013-2014 Nicolas Gryman <ngryman@gmail.com>
 * LGPL Licensed
 */

#ifndef __RIBS_OPERATION_H__
#define __RIBS_OPERATION_H__

#include "common.h"

namespace ribs {

/**
 * Abstract class representing a RIBS operation.
 * An operation may be seen as a worker class using libuv as infrastructure for threading.
 * This worker acts on an input and produces an output.
 */
class Operation {
public:
    void Enqueue();

    Operation(_NAN_METHOD_ARGS);
    virtual ~Operation();

protected:
    /**
     * Operation implementation.
     * This is where all the work is done to grasp the input and produce an output.
     * This method is called in another thread, managed by libuv.
     */
    virtual void Process() = 0;

    /**
     * Return the output value produced by the operation.
     * This will directly passed to the JavaScript callback if the operation succeeds.
     * This method is necessary as we can't interact with v8 in the DoProcess method. This cause segmentation faults,
     * probably because v8 is not thread safe or something like this.
     */
    virtual v8::Local<v8::Value> OutputValue() = 0;

    std::string  error;
    NanCallback* callback;
    uv_work_t    req;

    static void ProcessAsync(uv_work_t* req);
    static void AfterProcessAsync(uv_work_t* req);
};

/**
 * Helps calling a specific operation.
 */

#define _OP_NAME(name) name ## Operation
#define _OP_METHOD(name, method, ret, args, stub) ret _OP_NAME(name)::method(args) stub

#define OPERATION(name, stub)                 \
    class _OP_NAME(name) : public Operation { \
    public:                                   \
        _OP_NAME(name)(_NAN_METHOD_ARGS);     \
        virtual ~_OP_NAME(name)();            \
                                              \
    private:                                  \
        void                 Process();       \
        v8::Local<v8::Value> OutputValue();   \
        stub                                  \
    };

#define OPERATION_PREPARE(name, stub) _OP_METHOD(name, _OP_NAME(name), , _NAN_METHOD_ARGS, : Operation(args) stub)
#define OPERATION_CLEANUP(name, stub) _OP_METHOD(name, ~_OP_NAME(name), , void, stub)
#define OPERATION_PROCESS(name, stub) _OP_METHOD(name, Process, void, void, stub)
#define OPERATION_VALUE(name, stub)   _OP_METHOD(name, OutputValue, Local<Value>, void, stub)

#define RIBS_OPERATION(name)                                             \
    NanScope();                                                          \
    Operation* op;                                                       \
    try {                                                                \
        op = new _OP_NAME(name)(args);                                   \
    }                                                                    \
    catch (const std::exception& e) {                                    \
        return ThrowException(Exception::Error(String::New(e.what())));  \
    }                                                                    \
    op->Enqueue();                                                       \
    NanReturnUndefined();

}

#endif