diff --git a/README.md b/README.md index 0c7f40ce..beb6965f 100644 --- a/README.md +++ b/README.md @@ -6804,7 +6804,7 @@ You can chain the M\_LET\_IF macro to create several different variables. This macro registers the execution of 'clear\_code' when reaching the further closing brace of the next block of instruction. -clear_code shall be a valid expression. +clear\_code shall be a valid expression. There shall be at most one M\_DEFER macro per line of source code. @@ -6823,6 +6823,39 @@ You can use the break instruction to quit the block (the clear\_code will be executed) or you can use exception. +##### M\_CHAIN\_INIT(init\_code, clear\_code) + +This macro executes 'init\_code' then +registers the execution of 'clear\_code' if an exception is triggered +until the further closing brace of the next block of instruction. +init\_code and clear\_code shall be a valid expression. +If exception are not enabled, it simply executes 'init\_code'. + +There shall be at most one M\CHAIN\_INIT macro per line of source code. +It can be chained multiple times to register multiple registrations. + +Therefore it enables support for chaining +initialization at the begining of a constructor for the fields of the constructed +object so that even if the constructor failed and throw an exception, +the fields of the constructed object are properly cleared. + +This is equivalent to C++ construct: + + void type() : field1(), field2() { rest of constructor } + +M_CHAIN_INIT shall be the first instructions of the constructor function. + +Example: + + void struct_init_set(struct_t d, struct_t s) + { + M_CHAIN_INIT(string_init_set(d->s1, s->s1), string_clear(d->s1) ) + M_CHAIN_INIT(string_init_set(d->s2, s->s2), string_clear(d->s2) ) { + d->num = s->num; + } + } + + #### Memory / Error macros All these macro can be overridden before including the header m-core.h @@ -8065,6 +8098,11 @@ otherwise it will compile in degraded mode: -fblocks -lBlocksRuntime +When writing your own constructor, you should consider M\_CHAIN\_INIT +to support partially constructed object +if there are more than two source of throwing in your object +(any memory allocation is a source of throwing). + #### struct m\_exception\_s This is the exception type. It is composed of the following fields: diff --git a/doc/ISSUES.org b/doc/ISSUES.org index 311dbf0c..be14c19e 100644 --- a/doc/ISSUES.org +++ b/doc/ISSUES.org @@ -1,6 +1,24 @@ *Long term issues* ========================================================== +* TODO #33 : Handling of partially constructed object :ANOMALY: + +** State + +Support of partially constructed object needs special code to handle it +correctly (register a correct cleanup function in case of exception). + +Current containers don't support such features. + +** Actions + +Add such support in M*LIB containers. + +It can be difficult. For example, for array _init_set +function due to the copy of the object one per one. Each copied sub object +may throw an exception, so we always need to have the container in a correct +state so that it can be cleanup. + * TODO #32 : User specialization fields in the container :ENHANCEMENT: ** State @@ -145,7 +163,7 @@ containers provides static inline m_serial_return_code_t \ M_C(M_F(name, _out_serial),M_GET_NAME(serial_op) )(M_GET_TYPE(serial_op) f, const list_t list) \ -* TODO #29 : Support of partial initialized object :ANOMALY: +* DONE #29 : Support of partial initialized object :ANOMALY: ** State