Thread overview
store template value
Aug 01, 2015
maarten van damme
Aug 01, 2015
Adam D. Ruppe
Aug 01, 2015
maarten van damme
Aug 01, 2015
Adam D. Ruppe
Aug 01, 2015
maarten van damme
Aug 01, 2015
Ali Çehreli
Aug 02, 2015
maarten van damme
Aug 02, 2015
Ali Çehreli
August 01, 2015
I have a class that creates a task in it's constructor. How do I store this created task as one of it's value members and later on call .yieldForce()?


August 01, 2015
On Saturday, 1 August 2015 at 15:37:46 UTC, maarten van damme wrote:
> I have a class that creates a task in it's constructor. How do I store this created task as one of it's value members and later on call .yieldForce()?

If the class itself isn't templated on the type, you'll want to use something like std.variant.Variant to store it.
August 01, 2015
I was afraid I would have to do that. Templatizing the class on the value doesn't work as I later on want to create a hashmap of these classes. When I assign a task to a variant, how do I call .yieldForce later on?

2015-08-01 18:28 GMT+02:00 Adam D. Ruppe via Digitalmars-d-learn < digitalmars-d-learn@puremagic.com>:

> On Saturday, 1 August 2015 at 15:37:46 UTC, maarten van damme wrote:
>
>> I have a class that creates a task in it's constructor. How do I store this created task as one of it's value members and later on call .yieldForce()?
>>
>
> If the class itself isn't templated on the type, you'll want to use something like std.variant.Variant to store it.
>


August 01, 2015
On Saturday, 1 August 2015 at 16:41:54 UTC, maarten van damme wrote:
> I was afraid I would have to do that. Templatizing the class on the value doesn't work as I later on want to create a hashmap of these classes. When I assign a task to a variant, how do I call .yieldForce later on?


You can get a type from a Variant with the get!T method then call it.

But actually, maybe Task should just be an interface with the yieldForce method then you create classes that implement it and pass them to the constructor. Then there's no need for templates or casting at all.
August 01, 2015
But it's std.parallelism's task...
And how can I use get!T if I don't know the type of the task?

2015-08-01 19:02 GMT+02:00 Adam D. Ruppe via Digitalmars-d-learn < digitalmars-d-learn@puremagic.com>:

> On Saturday, 1 August 2015 at 16:41:54 UTC, maarten van damme wrote:
>
>> I was afraid I would have to do that. Templatizing the class on the value doesn't work as I later on want to create a hashmap of these classes. When I assign a task to a variant, how do I call .yieldForce later on?
>>
>
>
> You can get a type from a Variant with the get!T method then call it.
>
> But actually, maybe Task should just be an interface with the yieldForce method then you create classes that implement it and pass them to the constructor. Then there's no need for templates or casting at all.
>


August 01, 2015
On 08/01/2015 08:37 AM, maarten van damme via Digitalmars-d-learn wrote:
> I have a class that creates a task in it's constructor. How do I store this
> created task as one of it's value members and later on call .yieldForce()?
>

Tasks can be created with a function pointer 'function parameter' as well. (This has already been added to "Programming in D" but it is not available on the web site yet.)

I learned the exact type by the help of pragma(msg) below and used it to create MyTask and myTasks:

import std.parallelism;

double foo(int i)
{
    return i * 1.5;
}

double bar(int i)
{
    return i * 2.5;
}

void main()
{
    auto tasks = [ task(&foo, 1),
                   task(&bar, 2) ];    // ← compiles

    pragma(msg, typeof(tasks[0]));

    alias MyTask = Task!(run, double function(int), int)*;

    MyTask[] myTasks;
    myTasks ~= task(&foo, 1);
    myTasks ~= task(&bar, 2);
}

Ali

August 02, 2015
Oh, neat. This saves the day :)

2015-08-01 23:22 GMT+02:00 Ali Çehreli <digitalmars-d-learn@puremagic.com>:

> On 08/01/2015 08:37 AM, maarten van damme via Digitalmars-d-learn wrote:
>
>> I have a class that creates a task in it's constructor. How do I store
>> this
>> created task as one of it's value members and later on call .yieldForce()?
>>
>>
> Tasks can be created with a function pointer 'function parameter' as well. (This has already been added to "Programming in D" but it is not available on the web site yet.)
>
> I learned the exact type by the help of pragma(msg) below and used it to
> create MyTask and myTasks:
>
> import std.parallelism;
>
> double foo(int i)
> {
>     return i * 1.5;
> }
>
> double bar(int i)
> {
>     return i * 2.5;
> }
>
> void main()
> {
>     auto tasks = [ task(&foo, 1),
>                    task(&bar, 2) ];    // ← compiles
>
>     pragma(msg, typeof(tasks[0]));
>
>     alias MyTask = Task!(run, double function(int), int)*;
>
>     MyTask[] myTasks;
>     myTasks ~= task(&foo, 1);
>     myTasks ~= task(&bar, 2);
> }
>
> Ali
>
>


August 02, 2015
On 08/02/2015 05:15 AM, maarten van damme via Digitalmars-d-learn wrote:

> Oh, neat. This saves the day :)

Awesome! :) However, that solution depends on the implementation details of std.parallelism. It is possible to do the same thing by inheriting from an 'interface' and "hiding" the templated type under there.

The following program need not spell out the template instance:

import std.parallelism;

double foo(int i)
{
    return i * 1.5;
}

double bar(int i)
{
    return i * 2.5;
}

/* This is what the user code will need to know about. */
interface MyTask
{
    void executeInNewThread();
    void yieldForce();
}

/* This subclass hides the actual templated Task type. */
class MyTaskImpl(TaskType) : MyTask
{
    TaskType t;

    this(TaskType t)
    {
        this.t = t;
    }

    /* These two are to satisfy the interface requirements. */
    void executeInNewThread()
    {
        t.executeInNewThread();
    }

    void yieldForce()
    {
        t.yieldForce();
    }
}

/* A convenience function to hide the Task template instance. */
auto newMyTask(TaskType)(TaskType taskObject)
{
    return new MyTaskImpl!TaskType(taskObject);
}

void main()
{
    /* Populate */
    MyTask[] myTasks;
    myTasks ~= newMyTask(task!foo(1));
    myTasks ~= newMyTask(task!bar(2));

    import std.algorithm;

    /* Execute */
    myTasks.each!(t => t.executeInNewThread);

    /* Wait */
    myTasks.each!(t => t.yieldForce);
}

Ali