How would you create this construct?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Fri Mar 30 03:02:55 UTC 2018


On Friday, March 30, 2018 02:30:01 Chris Katko via Digitalmars-d-learn 
wrote:
> void start_draw_calls(BITMAP target_bitmap); //locks onto a
> resource
> void end_draw_calls(); //frees previous resource lock
>
> void my_function()
>      {
>      //...
>
>      start_draw_calls(target_bitmap) //whether this is a function,
> or class, lambda, or a "using"?
>          {
>          draw_call1();
>          draw_call2();
>          draw_call3();
>          } // end_draw_calls() is automatically called because
> we're hitting the closing curly.
>
>      //...
>      }
>
>
> The key here is, I've got a resource (setting a target bitmap)
> whose handling functions have to occur before, and after a series
> of user calls. (at which point target bitmap is restored to what
> it was before). So it's kind of like RAII (or maybe exactly like).
>
> What I'm trying to do is through this experimental API, is both
> eliminate the user needing to call a clean-up function
> explicitly, and, make the "right way" to use the API basically...
> the only way... to use it.
>
> The way I have written above, there is no way for you to leave
> my_function() without it automatically calling the cleaning up
> call. Even if you did a nested version, it would still work!
>
> At first glance, I could do:
>
>      start_draw_calls( {lambda containing all my code} )
>
> But that's not quite as pretty and you're forcing all code to be
> inside a lambda which... I'm not sure if that has hidden
> implications / gotchas for code.

If you want to force it, then just use RAII. Put @disable this(); in the
struct so that default initialization is disabled for the struct. Put
@disable this(this); in the struct so that it can't be copied (so that you
don't have to mess with something like reference counting). Then given the
struct a constructor that takes the resource to be locked, and make the
destructor unlock the resource. e.g. something like

struct S
{
public:

    @disable this();
    @disable this(this);

    this(BITMAMP bitmap)
    {
        _bitmap = bitmap;
        lock(_bitmap);
    }

    ~this()
    {
        unlock(_bitmap);
    }

private:

    BITMAP bitmap;
}

Now, you could just as easily do

    lock(bitmap);
    scope(exit) unlock(bitmap);

and get the same semantics, but that does require that the user explicitly
call the lock and unlock functions.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list