From: William <william.duclot@ensimag.grenoble-inp.fr>
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org, simon.rabourg@ensimag.grenoble-inp.fr,
francois.beutin@ensimag.grenoble-inp.fr,
antoine.queru@ensimag.grenoble-inp.fr,
matthieu.moy@grenoble-inp.fr, mhagger@alum.mit.edu
Subject: Re: [PATCH 2/2] strbuf: allow to use preallocated memory
Date: Tue, 31 May 2016 17:45:03 +0200 [thread overview]
Message-ID: <20160531154503.GA24895@Messiaen> (raw)
In-Reply-To: <xmqqbn3m7n25.fsf@gitster.mtv.corp.google.com>
On Mon, May 30, 2016 at 11:34:42PM -0700, Junio C Hamano wrote:
> William Duclot <william.duclot@ensimag.grenoble-inp.fr> writes:
>
>> The API contract is still respected:
>>
>> - The API users may peek strbuf.buf in-place until they perform an
>> operation that makes it longer (at which point the .buf pointer
>> may point at a new piece of memory).
>
> I think the contract is actually a bit stronger; the API reserves
> the right to free and reallocate a smaller chunk of memory if you
> make the string shorter, so peeked value of .buf will not be relied
> upon even if you didn't make it longer.
Right, anytime the string size change
>> - The API users may strbuf_detach() to obtain a piece of memory that
>> belongs to them (at which point the strbuf becomes empty), hence
>> needs to be freed by the callers.
>
> Shouldn't you be honuoring another API contract?
>
> - If you allow an instance of strbuf go out of scope without taking
> the ownership of the string by calling strbuf_detach(), you must
> release the resource by calling strbuf_release().
>
> As long as your "on stack strbuf" allows lengthening the string
> beyond the initial allocation (i.e. .alloc, not .len), the user of
> the API (i.e. the one that placed the strbuf on its stack) would not
> know when the implementation (i.e. the code in this patch) decides
> to switch to allocated memory, so it must call strbuf_release()
> before it leaves. Which in turn means that your implementation of
> strbuf_release() must be prepared to be take a strbuf that still has
> its string on the stack.
Well, my implementation does handle a strbuf that still has its
string on the stack: the buffer won't be freed in this case (only a
reset to STRBUF_INIT).
Unless I misunderstood you?
> On the other hand, if your "on stack strbuf" does not allow
> lengthening, I'd find such a "feature" pretty much useless. The
> caller must always test the remaining capacity, and switch to a
> dynamic strbuf, which is something the caller would expect the API
> implementation to handle silently. You obviously do not have to
> release the resource in such a case, but that is being convenient
> in the wrong part of the API.
>
> It would be wonderful if I can do:
>
> void func (void)
> {
> extern void use(char *[2]);
> /*
> * strbuf that uses 1024-byte on-stack buffer
> * initially, but it may be extended dynamically.
> */
> struct strbuf buf = STRBUF_INIT_ON_STACK(1024);
> char *x[2];
>
> strbuf_add(&buf, ...); /* add a lot of stuff */
> x[0] = strbuf_detach(&buf, NULL);
> strbuf_add(&buf, ...); /* do some stuff */
> x[1] = strbuf_detach(&buf, NULL);
> use(x);
>
> strbuf_release(&buf);
> }
>
> and add more than 2kb with the first add (hence causing buf to
> switch to dynamic scheme), the first _detach() gives the malloc()ed
> piece of memory to x[0] _and_ points buf.buf back to the on-stack
> buffer (and buf.alloc back to 1024) while setting buf.len to 0,
> so that the second _add() can still work purely on stack as long as
> it does not go beyond the 1024-byte on-stack buffer.
I think that it's possible, but extends the API beyond what was
originally intended by Michael. I don't see other use cases than treating
several string sequentially, is it worth avoiding a attach_movable()
(as suggested by Michael in place of wrap_preallocated())?
You could do:
void func (void)
{
extern void use(char *[2]);
/*
* strbuf that uses 1024-byte on-stack buffer
* initially, but it may be extended dynamically.
*/
char on_stack[1024];
struct strbuf buf;
char x[2];
strbuf_attach_movable(&sb, on_stack, 0, sizeof(on_stack));
strbuf_add(&buf, ...); /* add a lot of stuff */
x[0] = strbuf_detach(&buf, NULL);
strbuf_attach_movable(&sb, on_stack, 0, sizeof(on_stack));
strbuf_add(&buf, ...); /* do some stuff */
x[1] = strbuf_detach(&buf, NULL);
use(x);
strbuf_release(&buf);
}
Which seems pretty close without needing the strbuf API to remember the
original buffer or to even care about memory being on the stack or the
heap.
>> +/**
>> + * Flags
>> + * --------------
>> + */
>> +#define STRBUF_OWNS_MEMORY 1
>> +#define STRBUF_FIXED_MEMORY (1 << 1)
>
> This is somewhat a strange way to spell two flag bits. Either spell
> them as 1 and 2 (perhaps in octal or hexadecimal), or spell them as
> 1 shifted by 0 and 1 to the left. Don't mix the notation.
Noted
>> @@ -20,16 +28,37 @@ char strbuf_slopbuf[1];
>>
>> void strbuf_init(struct strbuf *sb, size_t hint)
>> {
>> + sb->flags = 0;
>> sb->alloc = sb->len = 0;
>> sb->buf = strbuf_slopbuf;
>> if (hint)
>> strbuf_grow(sb, hint);
>> }
>>
>> +void strbuf_wrap_preallocated(struct strbuf *sb, char *path_buf,
>> + size_t path_buf_len, size_t alloc_len)
>> +{
>> + if (!path_buf)
>> + die("you try to use a NULL buffer to initialize a strbuf");
>
> What does "path" mean in the context of this function (and its
> "fixed" sibling)?
That should be someting like `str` and `str_len` indeed
next prev parent reply other threads:[~2016-05-31 15:45 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-30 10:36 [PATCH 0/2] strbuf: improve API William Duclot
2016-05-30 10:36 ` [PATCH 1/2] strbuf: add tests William Duclot
2016-05-30 11:26 ` Johannes Schindelin
2016-05-30 13:42 ` Simon Rabourg
2016-05-30 11:56 ` Matthieu Moy
2016-05-31 2:04 ` Michael Haggerty
2016-05-31 9:48 ` Simon Rabourg
2016-05-30 10:36 ` [PATCH 2/2] strbuf: allow to use preallocated memory William Duclot
2016-05-30 12:13 ` Johannes Schindelin
2016-05-30 13:20 ` William Duclot
2016-05-31 6:21 ` Johannes Schindelin
2016-05-31 3:05 ` Michael Haggerty
2016-05-31 6:41 ` Johannes Schindelin
2016-05-31 8:25 ` Michael Haggerty
2016-05-30 12:52 ` Matthieu Moy
2016-05-30 14:15 ` William Duclot
2016-05-30 14:34 ` Matthieu Moy
2016-05-30 15:16 ` William Duclot
2016-05-31 4:05 ` Michael Haggerty
2016-05-31 15:59 ` William Duclot
2016-06-03 14:04 ` William Duclot
2016-05-30 21:56 ` Mike Hommey
2016-05-30 22:46 ` William Duclot
2016-05-30 22:50 ` Mike Hommey
2016-05-31 6:34 ` Junio C Hamano
2016-05-31 15:45 ` William [this message]
2016-05-31 15:54 ` Matthieu Moy
2016-05-31 16:08 ` William Duclot
2016-05-30 11:32 ` [PATCH 0/2] strbuf: improve API Remi Galan Alfonso
2016-06-01 7:42 ` Jeff King
2016-06-01 19:50 ` David Turner
2016-06-01 20:09 ` Jeff King
2016-06-01 20:22 ` David Turner
2016-06-01 21:07 ` Jeff King
2016-06-02 11:11 ` Michael Haggerty
2016-06-02 12:58 ` Matthieu Moy
2016-06-02 14:22 ` William Duclot
2016-06-24 17:20 ` Jeff King
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160531154503.GA24895@Messiaen \
--to=william.duclot@ensimag.grenoble-inp.fr \
--cc=antoine.queru@ensimag.grenoble-inp.fr \
--cc=francois.beutin@ensimag.grenoble-inp.fr \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=matthieu.moy@grenoble-inp.fr \
--cc=mhagger@alum.mit.edu \
--cc=simon.rabourg@ensimag.grenoble-inp.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).