How to inject a value known only at runtime using boost-di? - c++

I am learning to use boost::di and I fail to understand how one is expected to create multiple instances of the same type using different runtime parameters.
From what I understand, The documentation mostly focuses on creating a single object with the same parameters. I would like to create multiple objects using parameters that are known at runtime.
For example, I have the following type:
struct Device
{
int slot_;
Device(int slot) : slot_(slot) {}
};
The slot variable is determined only at runtime via user input.
Ideally, I would like to be able to do something like this:
auto device1 = injector.create<std::shared_ptr<Device>>(123); // slot = 123
auto device2 = injector.create<std::shared_ptr<Device>>(321); // slot = 321
Based on the documentation, This is what I managed so far:
auto injector = di::make_injector(
di::bind<Device>.to(
[&](const auto& injector)
{
// this assumes slot is a captured by the lambda
return std::make_shared<Device>(slot);
})
);
int slot = 123; // captured by lambda
auto device1 = injector.create<std::shared_ptr<Device>>();
slot = 321; // captured by lambda
auto device2 = injector.create<std::shared_ptr<Device>>();
I would like to avoid capturing the slot variable by the lambda. My real use case involves many runtime parameters for each type.
Is there a more elegant way to pass the runtime parameters to the injector at runtime?
What is the generic way to pass runtime parameters to constructors with boost::di?

Related

What's the proper way to have a Task that calls an arbitrary function with a known, specific return type?

I have a value which is expensive to calculate and can be asked for ahead of time--something like a lazily initiated value whose initialization is actually done at the moment of definition, but in a different thread. My immediate thought was to use parallelism.-Task seems purpose-built for this exact use-case. So, let's put it in a class:
class Foo
{
import std.parallelism : Task,task;
static int calculate(int a, int b)
{
return a+b;
}
private Task!(calculate,int,int)* ourTask;
private int _val;
int val()
{
return ourTask.workForce();
}
this(int a, int b)
{
ourTask = task!calculate(a,b);
}
}
That seems all well and good... except when I want the task to be based on a non-static method, in which case I want to make the task a delegate, in which case I start having to do stuff like this:
private typeof(task(&classFunc)) working;
And then, as it turns out, typeof(task(&classFunc)), when it's asked for outside of a function body, is actually Task!(run,ReturnType!classFunc function(Parameters!classFunc))*, which you may notice is not the type actually returned by runtime function calls of that. That would be Task!(run,ReturnType!classFunc delegate(Parameters!classFunc))*, which requires me to cast to typeof(working) when I actually call task(&classFunc). This is all extremely hackish feeling.
This was my attempt at a general template solution:
/**
Provides a transparent wrapper that allows for lazy
setting of variables. When lazySet!!func(args) is called
on the value, the function will be called in a new thread;
as soon as the value's access is attempted, it'll return the
result of the task, blocking if it's not done calculating.
Accessing the value is as simple as using it like the
type it's templated for--see the unit test.
*/
shared struct LazySet(T)
{
/// You can set the value directly, as normal--this throws away the current task.
void opAssign(T n)
{
import core.atomic : atomicStore;
working = false;
atomicStore(_val,n);
}
import std.traits : ReturnType;
/**
Called the same way as std.parallelism.task;
after this is called, the next attempt to access
the value will result in the value being set from
the result of the given function before it's returned.
If the task isn't done, it'll wait on the task to be done
once accessed, using workForce.
*/
void lazySet(alias func,Args...)(Args args)
if(is(ReturnType!func == T))
{
import std.parallelism : task,taskPool;
auto t = task!func(args);
taskPool.put(t);
curTask = (() => t.workForce);
working = true;
}
/// ditto
void lazySet(F,Args...)(F fpOrDelegate, ref Args args)
if(is(ReturnType!F == T))
{
import std.parallelism : task,taskPool;
auto t = task(fpOrDelegate,args);
taskPool.put(t);
curTask = (() => t.workForce);
working = true;
}
private:
T _val;
T delegate() curTask;
bool working = false;
T val()
{
import core.atomic : atomicStore,atomicLoad;
if(working)
{
atomicStore(_val,curTask());
working = false;
}
return atomicLoad(_val);
}
// alias this is inherently public
alias val this;
}
This lets me call lazySet using any function, function pointer or delegate that returns T, and then it'll calculate the value in parallel and return it, fully calculated, next time anything tries to access the underlying value, exactly as I wanted. Unit tests I wrote to describe its functionality pass, etc., it works perfectly.
But one thing's bothering me:
curTask = (() => t.workForce);
Moving the Task around by way of creating a lambda on-the-spot that happens to have the Task in its context still seems like I'm trying to "pull one over" on the language, even if it's less "hackish-feeling" than all the casting from earlier.
Am I missing some obvious language feature that would allow me to do this more "elegantly"?
Templates that take an alias function parameter (such as the Task family) are finicky regarding their actual type, as they can receive any type of function as parameter (including in-place delegates that get inferred themselves). As the actual function that gets called is part of the type itself, you would have to pass it to your custom struct to be able to save the Task directly.
As for the legitimacy of your solution, there is nothing wrong with storing lambdas to interact with complicated (or "hidden") types later.
An alternative is to store a pointer to &t.workForce directly.
Also, in your T val() two threads could enter if(working) at the same time, but I guess due to the atomic store it wouldn't really break anything - anyway, that could be fixed by core.atomic.cas.

How to pass the second parameter of ObjectTemplate::New in Google V8?

I know creating an ObjectTemplate and we can do several things to it. But my question is not about those well-known things.
I want to know how to pass the second parameter.
As the official guide said:
Each function template has an associated object template. This is used to configure objects created with this function as their constructor.
And the second parameter of ObjectTemplate::New is a constructor typed by FunctionTemplate.
static Local<ObjectTemplate> New(Isolate *isolate, Local<FunctionTemplate> constructor = Local<FunctionTemplate>());
That means something like this:
void Constructor(const FunctionCallbackInfo<Value>& args)
{
// ...
}
Local<FunctionTemplate> _constructor = FunctionTemplate::New(isolate, Constructor);
Local<ObjectTemplate> tpl = ObjectTemplate::New(isolate, _constructor);
Who can give me a demo that how to implement the Constructor function.
I tried this, but failed:
void Constructor(const FunctionCallbackInfo<Value>& args)
{
Isolate* isolate = args.GetIsolate();
args.This()->Set(String::NewFromUtf8(isolate, "value"), Number::New(isolate, 233));
args.GetReturnValue().Set(args.This());
}
By the way, I know the use case of accessors and so on, I just want to know how to use the second parameter.
There's an example for the second ObjectTemplate::New parameter in V8's API tests at https://chromium.googlesource.com/v8/v8/+/master/test/cctest/test-api.cc#1901:
LocalContext env;
Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
v8::Local<v8::String> class_name = v8_str("the_class_name");
fun->SetClassName(class_name);
Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
templ1->Set(isolate, "x", v8_num(10));
templ1->Set(isolate, "value", v8_num(233)); // From your last snippet.
Local<v8::Object> instance1 =
templ1->NewInstance(env.local()).ToLocalChecked();
CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
As you can see, there's no need to implement property creation indirectly via a FunctionTemplate, that's what the ObjectTemplate is for. See the "x" and "value" properties in the above example.
The quote you mentioned refers to something else. When you instantiate a function from a FunctionTemplate, then JavaScript code can use that function as a constructor. The mentioned ObjectTemplate can be used to configure the objects that will be created that way.

c# concurrent, overlapping callbacks

A short purely technical question:
If I have an uncertain amount of overlapping (time-wise) instances of the class below. Is it and how is it ensured, that the "this" in "call_back_when_done" belongs to the same "this" as it was in "Start"?
class MyClass{
int ident = -1;
bool ready = false;
void Start(string url){
ident = aStaticClass.DoSomethingAndForkThread(url, callback_when_done);
}
void call_back_when_done(){
ready = true;
}
}
e.g.:
for (int i=0; i < 3; i++)
new MyClass().Start(<aURL>);
Thank You
At first, you can bind the function to "this" like described here using currying : (How) is it possible to bind/rebind a method to work with a delegate of a different signature?
I would prefer a lambda function for your example case like described here : C# Lambdas and "this" variable scope
Lambda functions are bound to the scope of the "this" context where they are created. Members of your surrounding Class are automatically visible to the Lambda function. Using a Lambda function you'll get shorter code which can also better optimized by the compiler.
It is guaranteed.
When you pass callback_when_done to DoSomethingAndForkThread in Start, you are not only passing the raw function pointer (like you would in C++ with &MyClass::callback_when_done, but some kind of tuple consisting of the method to call and the object on which the method should be called (this).
If you like it more explicit you can also write a closure manually:
void Start(string url) {
var that = this; // that get's captured by the closure
ident = aStaticClass.DoSomethingAndForkThread(url, () => that.callback_when_done());
}

In lua is there a way to bind an upvalue to a userdata value instead of a function?

In the following example a userdata value is created of type MyType and a table is created with a metafunction __tostring which calls LI_MyType__tostring. The code creates a closure-based lua OOP. My gripe with the example provided is it appears as though there is only one way to associate userdata with a method call, via upvalues. In and of itself, this isn't problematic unless I want to share the same metatable across instances.
In an ideal world - and what I'm hoping to unearth with this question - is there a way to associate an upvalue with a value (e.g. userdata) without associating it with a function call via an upvalue? I'm hoping there is a trick that will let me continue to use closure-based lua OOP and share the same metatable across instances. I'm not optimistic, but I figured I'd ask to see if someone has a suggestion or a non-obvious trick.
using FuncArray = std::vector<const ::luaL_Reg>;
static const FuncArray funcs = {
{ "__tostring", LI_MyType__tostring },
};
int LC_MyType_newInstance(lua_State* L) {
auto userdata = static_cast<MyType*>(lua_newuserdata(L, sizeof(MyType)));
new(userdata) MyType();
// Create the metatable
lua_createtable(L, 0, funcs.size()); // |userdata|table|
lua_pushvalue(L, -2); // |userdata|table|userdata|
luaL_setfuncs(L, funcs.data(), 1); // |userdata|table|
lua_setmetatable(L, -2); // |userdata|
return 1;
}
int LI_MyType__tostring(lua_State* L) {
// NOTE: Blindly assume that upvalue 1 is my userdata
const auto n = lua_upvalueindex(1);
lua_pushvalue(L, n); // |userdata|
auto myTypeInst = static_cast<MyType*>(lua_touserdata(L, -1));
lua_pushstring(L, myTypeInst->str()); // |userdata|string|
return 1; // |userdata|string|
}
I'm hoping there's a way of performing something like (this is pseudo-code!):
// Assume that arg 1 is userdata
int LI_MyType__tostring(lua_State* L) {
const int stackPosition = -1;
const int upvalueIndex = 1;
const auto n = lua_get_USERDATA_upvalue(L, stackPosition, upvalueIndex);
lua_pushvalue(L, n); // |userdata|
auto myTypeInst = static_cast<MyType*>(lua_touserdata(L, -1));
lua_pushstring(L, myTypeInst->str()); // |userdata|string|
return 1; // |userdata|string|
}
I know this is similar to how things would be for the "normal" metatable style of OOP, but I want to keep things closure based and avoid introducing the colon syntax.
Another way of asking this question would be, is there a way to share metatables across userdata instances while using a closure-based OOP? Using lua's syntax from the scripting side of things, I don't think it's possible, but I'm hoping there's something that can be done on the C side of things.
UPDATE (2013-10-10): Based on #lhf's answer to use lua_setuservalue() and lua_getuservalue() the protocol I've settled on which allows me to reuse metatables is this:
Register a single metatable object using luaL_newmetatable(). This metatable can now be shared across userdata instances because no upvalues are used when registering the metatable.
Create a userdata value (lua_newuserdata()).
Assign the correct metatable to the userdata value (lua_setmetatable()).
Create and populate an instance method calls/attributes table with one upvalue, the userdata.
Use lua_setuservalue() on userdata to store a reference to the per-instance attribute/method table.
Change various metamethods (e.g. __index) to use the userdata's uservalue table.
As a consequence:
upvalues are never used in metamethods
upvalues are only used in a value's instance methods
there is only one extra table per instance of a given class
It's still not possible to escape creating a method/attribute table per userdata, but that overhead is nominal. It would be nice if obj.myMethod() would pass obj to function myMethod() somehow without using :, but that's exactly what : does because this isn't possible another way (unless you do make use of an upvalue).
lua_setuservalue seems to be exactly what you need. There is also of course lua_getuservalue.
(I'm skipping the C++ code and answering the question in the title.)
I don't think you should be trying to do it exactly, for a few reasons.
If you call object.method(), and you try to infer the object from the instance that was created, you're blocking your ability to pass function pointers around that behave on any object given.
You have cyclic references to objects that will never get garbage collected (each instance's function pointing back to the instance).
Just get the object from slot 1, and check its type matches your userdata. (luaL_checkudata)
If its not an object and tostring is called for example, just output that its a class of object name, instead of the instance details. It makes far more sense, and may well make debugging simpler if the object reports what it actually is, rather than trying to be too clever and misleading you.

How to pass a wrapped C++ object to a Javascript callback?

I'm trying to write a Node.js module, using C++, that wraps and exposes some classes from libhdf5.
I'm currently interested in two classes from libhdf5. The first one is File, and it opens an hdf5 file. The second one is Group, and it represents groups within that file. You get Group objects from a File object.
I've written some code in which I create a File object and attempt to get a Group from it. I am trying to make my Node.js module as JavaScripty as possible, so I want to return the group using a callback. So, I am trying to code my module so that it's used like this:
var hdf5 = require('hdf5');
var file = new hdf5.File('/tmp/example.h5');
file.getGroup('foobar', function (err, group) { console.log(group); });
So, in the C++ code for my File wrapper, I'd have a function that maps to the getGroup function here, and it'd call the given anonymous function, passing in any errors as well as the new Group object wrapper.
Given that this sounded to me like what the Node.js documentation shows to be a factory of wrapped objects, I have modeled my Group code after the examples there.
So, I have my Group wrapper coded up, but am stuck trying to instantiate it. I don't know enough yet to know how to stray away from using the v8 Arguments class for function parameters. Because of that, I can't seem to be able to pass in some parameters that I need for my v8 persistent constructor function (because I am instantiating this from C++, and not from JS-land).
You are almost there. You don't need to pass Arguments to Group::Instantiate. Just pass what you need and use the constructor to create the new instance of Group. For example:
Handle<Value> Group::Instantiate(const std::string& name) {
HandleScope scope;
Local<v8::Value> argv[1] = {
Local<v8::Value>::New(String::New(name.c_str()))
};
return scope.Close(Constructor->NewInstance(1, argv));
}
The method Group::New does the rest of the construction work.
Handle<Value> Group::New(const Arguments& args) {
HandleScope scope;
if (!args[0]->IsString()) {
return ThrowException(Exception::TypeError(String::New("First argument must be a string")));
}
const std::string name(*(String::Utf8Value(args[0]->ToString())));
Group * const group = new Group(name);
bar->Wrap(args.This());
return args.This();
}
In File::OpenGroup you can do this:
Handle<Value> File::OpenGroup (const Arguments& args) {
HandleScope scope;
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsFunction()) {
ThrowException(Exception::SyntaxError(String::New("expected name, callback")));
return scope.Close(Undefined());
}
const std::string name(*(String::Utf8Value(args[0]->ToString())));
Local<Function> callback = Local<Function>::Cast(args[1]);
const unsigned argc = 2;
Local<Value> argv[argc] = {
Local<Value>::New(Null()),
Local<Value>::New(Group::Instantiate(name))
};
callback->Call(Context::GetCurrent()->Global(), argc, argv);
return scope.Close(Undefined());
}