Author: tridge Date: 2006-09-13 00:05:07 +0000 (Wed, 13 Sep 2006) New Revision: 18435
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=18435 Log: added a function talloc_move() which is like talloc_steal(), but is meant for moving pointers between structures. The difference is that talloc_move() will zero the source pointer, thus ensuring you don't reference the pointer in the old context. talloc_move() is appropriate in some, but not all cases where we use talloc_steal() now. The interface came out of a discussion with Jeremy. Modified: branches/SAMBA_4_0/source/lib/talloc/talloc.3.xml branches/SAMBA_4_0/source/lib/talloc/talloc.c branches/SAMBA_4_0/source/lib/talloc/talloc.h branches/SAMBA_4_0/source/lib/talloc/testsuite.c Changeset: Modified: branches/SAMBA_4_0/source/lib/talloc/talloc.3.xml =================================================================== --- branches/SAMBA_4_0/source/lib/talloc/talloc.3.xml 2006-09-12 22:26:19 UTC (rev 18434) +++ branches/SAMBA_4_0/source/lib/talloc/talloc.3.xml 2006-09-13 00:05:07 UTC (rev 18435) @@ -369,7 +369,7 @@ known so the type-safe talloc_realloc() cannot be used. </para> </refsect2> - <refsect2><title>void *talloc_steal(const void *<emphasis role="italic">new_ctx</emphasis>, const void *<emphasis role="italic">ptr</emphasis>);</title> + <refsect2><title>TYPE *talloc_steal(const void *<emphasis role="italic">new_ctx</emphasis>, const TYPE *<emphasis role="italic">ptr</emphasis>);</title> <para> The talloc_steal() function changes the parent context of a talloc pointer. It is typically used when the context that the @@ -387,6 +387,16 @@ data if you do this. </para> </refsect2> + <refsect2><title>TYPE *talloc_move(const void *<emphasis role="italic">new_ctx</emphasis>, TYPE *<emphasis role="italic">ptr</emphasis>);</title> + <para> + The talloc_move() function is a wrapper around + talloc_steal() which zeros the source pointer after the + move. This avoids a potential source of bugs where a + programmer leaves a pointer in two structures, and uses the + pointer from the old structure after it has been moved to a + new one. + </para> + </refsect2> <refsect2><title>size_t talloc_total_size(const void *<emphasis role="italic">ptr</emphasis>);</title> <para> The talloc_total_size() function returns the total size in bytes Modified: branches/SAMBA_4_0/source/lib/talloc/talloc.c =================================================================== --- branches/SAMBA_4_0/source/lib/talloc/talloc.c 2006-09-12 22:26:19 UTC (rev 18434) +++ branches/SAMBA_4_0/source/lib/talloc/talloc.c 2006-09-13 00:05:07 UTC (rev 18435) @@ -738,6 +738,17 @@ } /* + a wrapper around talloc_steal() for situations where you are moving a pointer + between two structures, and want the old pointer to be set to NULL +*/ +void *_talloc_move(const void *new_ctx, const void **pptr) +{ + void *ret = _talloc_steal(new_ctx, *pptr); + (*pptr) = NULL; + return ret; +} + +/* return the total size of a talloc pool (subtree) */ size_t talloc_total_size(const void *ptr) Modified: branches/SAMBA_4_0/source/lib/talloc/talloc.h =================================================================== --- branches/SAMBA_4_0/source/lib/talloc/talloc.h 2006-09-12 22:26:19 UTC (rev 18434) +++ branches/SAMBA_4_0/source/lib/talloc/talloc.h 2006-09-13 00:05:07 UTC (rev 18435) @@ -65,15 +65,16 @@ /* this extremely strange macro is to avoid some braindamaged warning stupidity in gcc 4.1.x */ #define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; }) -#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr)) #else #define talloc_set_destructor(ptr, function) \ _talloc_set_destructor((ptr), (int (*)(void *))(function)) #define _TALLOC_TYPEOF(ptr) void * #define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)) -#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr)) #endif +#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr)) +#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_move((ctx),&(ptr)) + /* useful macros for creating type checked pointers */ #define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) #define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) @@ -127,6 +128,7 @@ void talloc_free_children(void *ptr); void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); void *_talloc_steal(const void *new_ctx, const void *ptr); +void *_talloc_move(const void *new_ctx, const void **pptr); size_t talloc_total_size(const void *ptr); size_t talloc_total_blocks(const void *ptr); void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, Modified: branches/SAMBA_4_0/source/lib/talloc/testsuite.c =================================================================== --- branches/SAMBA_4_0/source/lib/talloc/testsuite.c 2006-09-12 22:26:19 UTC (rev 18434) +++ branches/SAMBA_4_0/source/lib/talloc/testsuite.c 2006-09-13 00:05:07 UTC (rev 18435) @@ -731,6 +731,40 @@ } /* + test move +*/ +static bool test_move(void) +{ + void *root; + struct t_move { + char *p; + int *x; + } *t1, *t2; + printf("TESTING MOVE\n"); + + root = talloc_new(NULL); + + t1 = talloc(root, struct t_move); + t2 = talloc(root, struct t_move); + t1->p = talloc_strdup(t1, "foo"); + t1->x = talloc(t1, int); + *t1->x = 42; + + t2->p = talloc_move(t2, t1->p); + t2->x = talloc_move(t2, t1->x); + if (t1->p != NULL || t1->x != NULL || + strcmp(t2->p, "foo") || + *t2->x != 42) { + printf("talloc move failed\n"); + return false; + } + + talloc_free(root); + + return true; +} + +/* test talloc_realloc_fn */ static bool test_realloc_fn(void) @@ -1022,6 +1056,7 @@ ret &= test_realloc(); ret &= test_realloc_child(); ret &= test_steal(); + ret &= test_move(); ret &= test_unref_reparent(); ret &= test_realloc_fn(); ret &= test_type();