Was: Re: Vote for std.process

Manu turkeyman at gmail.com
Fri Apr 12 09:03:59 PDT 2013


On 13 April 2013 01:29, Vladimir Panteleev <vladimir at thecybershadow.net>wrote:

> On Friday, 12 April 2013 at 14:58:10 UTC, Manu wrote:
>
>> I didn't see any attempt to index the array by key in this case. That's
>> what an AA is for, and it's not being used here, so it's not a job for an
>> AA.
>>
>
> Sorry, not following.
>
> Are you suggesting to use a dynamic array for creating processes, but an
> associative array for examining the current process's environment?


I didn't see anywhere where it was possible to example the current
processed environment? I only saw the mechanism for feeding additional env
vars to the system command.
Linear array of key/value pair struct would be fine.

I wouldn't use env ~= "FOO=BAR";
>> I would use env ~= EnvVar("FOO", "BAR");
>> Or whatever key/value pair structure you like.
>>
>
> OK, but I don't see how it changes your argument. Also, you mentioned
> string[] earlier.


Sorry. I didn't think it through at the time.

It starts as soon as the majority agree it's important enough to enforce.
>>
> Although I think a tool like: char[len] stackString; would be a
>> super-useful tool to make this considerably more painless. Some C
>> compilers
>> support this.
>>
>
> I believe this is the feature:
>
> http://en.wikipedia.org/wiki/**Variable-length_array<http://en.wikipedia.org/wiki/Variable-length_array>
>
> It is part of C99.
>
> ------------------------------**------------------------------**-
>
> Earlier today, I wrote:
>
>  Please rewrite some part of std.process with performance in mind, and
>> post it here for review. This way, we can analyze the benefits and
>> drawbacks based on a concrete example, instead of vapor and hot air.
>>
>
> I've tried doing this myself, for the bit of code you brought up
> (constructing environment variables). Here's what I ended up with:
>
> ------------------------------**------------------------------**-
>
> import std.array;
>
> private struct StaticAppender(size_t SIZE, T)
> {
>     T[SIZE] buffer = void;
>     Appender!(T[]) appender;
>     alias appender this;
> }
>
> /// Returns a struct containing a fixed-size buffer and an
> /// appender. The appender will use the buffer (which has
> /// SIZE elements) until it runs out of space, at which
> /// point it will reallocate itself on the heap.
> auto staticAppender(size_t SIZE, T)()
> {
>     StaticAppender!(SIZE, T) result;
>     result.appender = appender(result.buffer[]);
>     return result;
> }
>
> /// Allows allocating a T[] given a size.
> /// Contains a fized-size buffer of T elements with SIZE
> /// length. When asked to allocate an array with
> /// length <= than SIZE, the buffer is used instead of
> /// the heap.
> struct StaticArray(size_t SIZE, T)
> {
>     T[SIZE] buffer = void;
>     T[] get(size_t size)
>     {
>         if (size <= SIZE)
>         {
>             buffer[0..size] = T.init;
>             return buffer[0..size];
>         }
>         else
>             return new T[size];
>     }
> }
>
> // ------------------------------**--------------------------
>
> void exec(const(char)*[] envz) { /+ ... +/ }
>
> void oldWay(string[string] environment)
> {
>     auto envz = new const(char)*[environment.**length + 1];
>     int pos = 0;
>     foreach (var, val; environment)
>
>         envz[pos++] = (var~'='~val~'\0').ptr;
>
>     exec(envz);
> }
>
> void newWay(string[string] environment)
> {
>     auto buf = staticAppender!(4096, char)();
>     StaticArray!(64, size_t) envpBuf;
>     size_t[] envp = envpBuf.get(environment.length + 1);
>
>     size_t pos;
>     foreach (var, val; environment)
>     {
>         envp[pos++] = buf.data.length;
>         buf.put(var);
>         buf.put('=');
>         buf.put(val);
>         buf.put('\0');
>     }
>
>     // Convert offsets to pointers in-place
>     auto envz = cast(const(char)*[])envp;
>     foreach (n; 0..pos)
>         envz[n] += cast(size_t)buf.data.ptr;
>
>     exec(envz);
> }
>
> ------------------------------**------------------------------**-
>
> As you can see, the code is quite more verbose, even with the helper
> types. It's no longer obvious at a glance what the code is doing. Perhaps
> you can come up with better abstractions?
>

Beautiful! Actually, I think if you look a couple of pages below, I think
you'll see something rather like that already there in the windows code.

Thought not sure why you use a size_t array which you just cast to a char*
array?
I think you could also fold that into one pass, rather than 2.
And I'm not sure about this line: envz[n] += cast(size_t)buf.data.ptr;

But those helpers make the problem rather painless.
I wonder if there's opportunity for improvement by having appender support
the ~ operator? Might be able to jig it to use natural concat syntax rather
than put()...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20130413/6cf127de/attachment.html>


More information about the Digitalmars-d mailing list