<commit_before>#ifndef _OPENCOG_ATOMSPACE_REQUEST_H
#define _OPENCOG_ATOMSPACE_REQUEST_H

#include <iostream>
#include <pthread.h>
#include <boost/scoped_ptr.hpp>
#include <boost/thread.hpp>

#include "AtomSpaceImpl.h"
#include "Handle.h"
#include "types.h"

using namespace std;

namespace opencog {

class ASRequest {
    //! Overkill, but doing atomic operations on bool is not technically threadsafe
    mutable boost::mutex complete_mutex;
    bool completed;
protected:
    //! For signalling that the request has been completed
    boost::condition_variable complete_cond;
    //! For blocking while fulfilling the request
    mutable boost::mutex the_mutex;

    AtomSpaceImpl* atomspace;
public:
    ASRequest() : completed(false) {};

    void set_atomspace(AtomSpaceImpl* as) {
        boost::mutex::scoped_lock lock(the_mutex);
        atomspace = as;
    }
    //! We wrap the actual do_work thread so that it doesn't have
    //! to worry about obtaining the lock or notifying of completion
    void run() {
        boost::mutex::scoped_lock lock(the_mutex);
        do_work();
        boost::mutex::scoped_lock lock2(complete_mutex);
        completed = true;
        complete_cond.notify_all();
    }
    virtual void do_work() = 0;

    bool is_complete() {
        // Rely on separate mutex for complete, since we don't want to stall
        // if the do_work method takes a while.
        boost::mutex::scoped_lock lock(complete_mutex);
        return completed;
    }
};

class AtomSpace;

/**
 * Request that stores and returns type T
 */
template<typename T>
class GenericASR: public ASRequest {

    friend class AtomSpace;
protected:
    T result;
    void set_result(T _result) { result = _result; }
public:
    GenericASR(AtomSpaceImpl* a){ set_atomspace(a); };

    virtual void do_work() = 0;

    T get_result() {
        boost::mutex::scoped_lock lock(the_mutex);
        if (!is_complete()) complete_cond.wait(lock);
        return result;
    }

};

/**
 * These should be replaced by variadic templates, or we should just replace
 * arguments with protocol buffers.
 */
template<typename T, typename A>
class OneParamASR: public GenericASR<T> {
protected:
    A p1;
public:
    OneParamASR(AtomSpaceImpl *a, const A& param1) : GenericASR<T>(a) {
        p1 = param1;
    }
};

template<typename T, typename A, typename B>
class TwoParamASR: public GenericASR<T> {
protected:
    A p1;
    B p2;
public:
    TwoParamASR(AtomSpaceImpl *a, const A& param1, const B& param2) : GenericASR<T>(a) {
        p1 = param1;
        p2 = param2;
    }
};

template<typename T, typename A, typename B, typename C>
class ThreeParamASR: public GenericASR<T> {
protected:
    A p1;
    B p2;
    C p3;
public:
    ThreeParamASR(AtomSpaceImpl *a, const A& param1, const B& param2, const C& param3) : GenericASR<T>(a) {
        p1 = param1;
        p2 = param2;
        p3 = param3;
    }
};

class AddNodeASR : public ThreeParamASR <Handle,Type,std::string,const TruthValue*> {
public:
    AddNodeASR(AtomSpaceImpl *a, Type type, const std::string& name, const TruthValue* tvn) :
        ThreeParamASR<Handle,Type,std::string,const TruthValue*>(a,type,name,tvn)
        { };
    ~AddNodeASR() {
        // clean up TruthValue as we are responsible for any passed parameters.
        if (!p3->isNullTv())
            delete p3;
    }
    
    virtual void do_work() {
        Handle r;
        try {
            Handle r = atomspace->addNode(p1, p2, *p3);
            set_result(r);
        } catch (InvalidParamException &e) {
            logger().error(e.what());
            set_result(r);
        }
    };
    
};

class AddLinkASR : public ThreeParamASR <Handle,Type,HandleSeq,const TruthValue*> {
public:
    AddLinkASR(AtomSpaceImpl *a, Type type, const HandleSeq& outgoing, const TruthValue* tvn) :
        ThreeParamASR<Handle,Type,HandleSeq,const TruthValue*>(a,type,outgoing,tvn)
        {};
    ~AddLinkASR() {
        // clean up TruthValue as we are responsible for any passed parameters.
        if (!p3->isNullTv())
            delete p3;
    }
    
    virtual void do_work() {
        set_result(atomspace->addLink(p1, p2, *p3));
    };
    
};

class GetNodeHandleASR : public TwoParamASR <Handle,Type,std::string> {
public:
    GetNodeHandleASR(AtomSpaceImpl *a, Type type, const std::string& name) :<commit_msg>Need to catch exceptions for addlink<commit_after>#ifndef _OPENCOG_ATOMSPACE_REQUEST_H
#define _OPENCOG_ATOMSPACE_REQUEST_H

#include <iostream>
#include <pthread.h>
#include <boost/scoped_ptr.hpp>
#include <boost/thread.hpp>

#include "AtomSpaceImpl.h"
#include "Handle.h"
#include "types.h"

using namespace std;

namespace opencog {

class ASRequest {
    //! Overkill, but doing atomic operations on bool is not technically threadsafe
    mutable boost::mutex complete_mutex;
    bool completed;
protected:
    //! For signalling that the request has been completed
    boost::condition_variable complete_cond;
    //! For blocking while fulfilling the request
    mutable boost::mutex the_mutex;

    AtomSpaceImpl* atomspace;
public:
    ASRequest() : completed(false) {};

    void set_atomspace(AtomSpaceImpl* as) {
        boost::mutex::scoped_lock lock(the_mutex);
        atomspace = as;
    }
    //! We wrap the actual do_work thread so that it doesn't have
    //! to worry about obtaining the lock or notifying of completion
    void run() {
        boost::mutex::scoped_lock lock(the_mutex);
        do_work();
        boost::mutex::scoped_lock lock2(complete_mutex);
        completed = true;
        complete_cond.notify_all();
    }
    virtual void do_work() = 0;

    bool is_complete() {
        // Rely on separate mutex for complete, since we don't want to stall
        // if the do_work method takes a while.
        boost::mutex::scoped_lock lock(complete_mutex);
        return completed;
    }
};

class AtomSpace;

/**
 * Request that stores and returns type T
 */
template<typename T>
class GenericASR: public ASRequest {

    friend class AtomSpace;
protected:
    T result;
    void set_result(T _result) { result = _result; }
public:
    GenericASR(AtomSpaceImpl* a){ set_atomspace(a); };

    virtual void do_work() = 0;

    T get_result() {
        boost::mutex::scoped_lock lock(the_mutex);
        if (!is_complete()) complete_cond.wait(lock);
        return result;
    }

};

/**
 * These should be replaced by variadic templates, or we should just replace
 * arguments with protocol buffers.
 */
template<typename T, typename A>
class OneParamASR: public GenericASR<T> {
protected:
    A p1;
public:
    OneParamASR(AtomSpaceImpl *a, const A& param1) : GenericASR<T>(a) {
        p1 = param1;
    }
};

template<typename T, typename A, typename B>
class TwoParamASR: public GenericASR<T> {
protected:
    A p1;
    B p2;
public:
    TwoParamASR(AtomSpaceImpl *a, const A& param1, const B& param2) : GenericASR<T>(a) {
        p1 = param1;
        p2 = param2;
    }
};

template<typename T, typename A, typename B, typename C>
class ThreeParamASR: public GenericASR<T> {
protected:
    A p1;
    B p2;
    C p3;
public:
    ThreeParamASR(AtomSpaceImpl *a, const A& param1, const B& param2, const C& param3) : GenericASR<T>(a) {
        p1 = param1;
        p2 = param2;
        p3 = param3;
    }
};

class AddNodeASR : public ThreeParamASR <Handle,Type,std::string,const TruthValue*> {
public:
    AddNodeASR(AtomSpaceImpl *a, Type type, const std::string& name, const TruthValue* tvn) :
        ThreeParamASR<Handle,Type,std::string,const TruthValue*>(a,type,name,tvn)
        { };
    ~AddNodeASR() {
        // clean up TruthValue as we are responsible for any passed parameters.
        if (!p3->isNullTv())
            delete p3;
    }
    
    virtual void do_work() {
        Handle r;
        try {
            r = atomspace->addNode(p1, p2, *p3);
            set_result(r);
        } catch (InvalidParamException &e) {
            logger().error(e.what());
            set_result(r);
        }
    };
    
};

class AddLinkASR : public ThreeParamASR <Handle,Type,HandleSeq,const TruthValue*> {
public:
    AddLinkASR(AtomSpaceImpl *a, Type type, const HandleSeq& outgoing, const TruthValue* tvn) :
        ThreeParamASR<Handle,Type,HandleSeq,const TruthValue*>(a,type,outgoing,tvn)
        {};
    ~AddLinkASR() {
        // clean up TruthValue as we are responsible for any passed parameters.
        if (!p3->isNullTv())
            delete p3;
    }
    
    virtual void do_work() {
        Handle r;
        try {
            r = atomspace->addLink(p1, p2, *p3);
            set_result(r);
        } catch (InvalidParamException &e) {
            logger().error(e.what());
            set_result(r);
        }
    };
    
};

class GetNodeHandleASR : public TwoParamASR <Handle,Type,std::string> {
public:
    GetNodeHandleASR(AtomSpaceImpl *a, Type type, const std::string& name) :
{'fraction_non_alphanumeric': 0.11052335396736072, 'fraction_numerical': 0.008328643781654474, 'mean_word_length': 2.921447484554281, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6117806', 'n_tokens_mistral': 2888, 'n_tokens_neox': 2841, 'n_words': 784}