mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-21 12:10:26 +02:00
libguile examples use scm_c_vector functions instead of SCM_SIMPLE_VECTOR_*
* doc/ref/libguile-concepts.texi (Multi-Threading): Use functions in the example instead of macros. Performance is really not a concern with this interface, especially now that scm_car and scm_cdr are inline functions.
This commit is contained in:
parent
5b70b4e284
commit
f0b6d8c71d
1 changed files with 24 additions and 25 deletions
|
@ -1,6 +1,6 @@
|
||||||
@c -*-texinfo-*-
|
@c -*-texinfo-*-
|
||||||
@c This is part of the GNU Guile Reference Manual.
|
@c This is part of the GNU Guile Reference Manual.
|
||||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010
|
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010, 2013
|
||||||
@c Free Software Foundation, Inc.
|
@c Free Software Foundation, Inc.
|
||||||
@c See the file guile.texi for copying conditions.
|
@c See the file guile.texi for copying conditions.
|
||||||
|
|
||||||
|
@ -492,12 +492,12 @@ my_list_to_vector (SCM list)
|
||||||
SCM vector = scm_make_vector (scm_length (list), SCM_UNDEFINED);
|
SCM vector = scm_make_vector (scm_length (list), SCM_UNDEFINED);
|
||||||
size_t len, i;
|
size_t len, i;
|
||||||
|
|
||||||
len = SCM_SIMPLE_VECTOR_LENGTH (vector);
|
len = scm_c_vector_length (vector);
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < len && scm_is_pair (list))
|
while (i < len && scm_is_pair (list))
|
||||||
@{
|
@{
|
||||||
SCM_SIMPLE_VECTOR_SET (vector, i, SCM_CAR (list));
|
scm_c_vector_set_x (vector, i, scm_car (list));
|
||||||
list = SCM_CDR (list);
|
list = scm_cdr (list);
|
||||||
i++;
|
i++;
|
||||||
@}
|
@}
|
||||||
|
|
||||||
|
@ -514,22 +514,23 @@ But there is no guarantee that the list referenced by @var{list} is not
|
||||||
modified in another thread while the loop iterates over it. Thus, while
|
modified in another thread while the loop iterates over it. Thus, while
|
||||||
copying its elements into the vector, the list might get longer or
|
copying its elements into the vector, the list might get longer or
|
||||||
shorter. For this reason, the loop must check both that it doesn't
|
shorter. For this reason, the loop must check both that it doesn't
|
||||||
overrun the vector (@code{SCM_SIMPLE_VECTOR_SET} does no range-checking)
|
overrun the vector and that it doesn't overrun the list. Otherwise,
|
||||||
and that it doesn't overrun the list (@code{SCM_CAR} and @code{SCM_CDR}
|
@code{scm_c_vector_set_x} would raise an error if the index is out of
|
||||||
likewise do no type checking).
|
range, and @code{scm_car} and @code{scm_cdr} would raise an error if the
|
||||||
|
value is not a pair.
|
||||||
|
|
||||||
It is safe to use @code{SCM_CAR} and @code{SCM_CDR} on the local
|
It is safe to use @code{scm_car} and @code{scm_cdr} on the local
|
||||||
variable @var{list} once it is known that the variable contains a pair.
|
variable @var{list} once it is known that the variable contains a pair.
|
||||||
The contents of the pair might change spontaneously, but it will always
|
The contents of the pair might change spontaneously, but it will always
|
||||||
stay a valid pair (and a local variable will of course not spontaneously
|
stay a valid pair (and a local variable will of course not spontaneously
|
||||||
point to a different Scheme object).
|
point to a different Scheme object).
|
||||||
|
|
||||||
Likewise, a simple vector such as the one returned by
|
Likewise, a vector such as the one returned by @code{scm_make_vector} is
|
||||||
@code{scm_make_vector} is guaranteed to always stay the same length so
|
guaranteed to always stay the same length so that it is safe to only use
|
||||||
that it is safe to only use SCM_SIMPLE_VECTOR_LENGTH once and store the
|
scm_c_vector_length once and store the result. (In the example,
|
||||||
result. (In the example, @var{vector} is safe anyway since it is a
|
@var{vector} is safe anyway since it is a fresh object that no other
|
||||||
fresh object that no other thread can possibly know about until it is
|
thread can possibly know about until it is returned from
|
||||||
returned from @code{my_list_to_vector}.)
|
@code{my_list_to_vector}.)
|
||||||
|
|
||||||
Of course the behavior of @code{my_list_to_vector} is suboptimal when
|
Of course the behavior of @code{my_list_to_vector} is suboptimal when
|
||||||
@var{list} does indeed get asynchronously lengthened or shortened in
|
@var{list} does indeed get asynchronously lengthened or shortened in
|
||||||
|
@ -547,11 +548,11 @@ my_pedantic_list_to_vector (SCM list)
|
||||||
SCM vector = scm_make_vector (scm_length (list), SCM_UNDEFINED);
|
SCM vector = scm_make_vector (scm_length (list), SCM_UNDEFINED);
|
||||||
size_t len, i;
|
size_t len, i;
|
||||||
|
|
||||||
len = SCM_SIMPLE_VECTOR_LENGTH (vector);
|
len = scm_c_vector_length (vector);
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < len)
|
while (i < len)
|
||||||
@{
|
@{
|
||||||
SCM_SIMPLE_VECTOR_SET (vector, i, scm_car (list));
|
scm_c_vector_set_x (vector, i, scm_car (list));
|
||||||
list = scm_cdr (list);
|
list = scm_cdr (list);
|
||||||
i++;
|
i++;
|
||||||
@}
|
@}
|
||||||
|
@ -560,12 +561,10 @@ my_pedantic_list_to_vector (SCM list)
|
||||||
@}
|
@}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
This version uses the type-checking and thread-robust functions
|
This version relies on the error-checking behavior of @code{scm_car} and
|
||||||
@code{scm_car} and @code{scm_cdr} instead of the faster, but less robust
|
@code{scm_cdr}. When the list is shortened (that is, when @var{list}
|
||||||
macros @code{SCM_CAR} and @code{SCM_CDR}. When the list is shortened
|
holds a non-pair), @code{scm_car} will throw an error. This might be
|
||||||
(that is, when @var{list} holds a non-pair), @code{scm_car} will throw
|
preferable to just returning a half-initialized vector.
|
||||||
an error. This might be preferable to just returning a half-initialized
|
|
||||||
vector.
|
|
||||||
|
|
||||||
The API for accessing vectors and arrays of various kinds from C takes a
|
The API for accessing vectors and arrays of various kinds from C takes a
|
||||||
slightly different approach to thread-robustness. In order to get at
|
slightly different approach to thread-robustness. In order to get at
|
||||||
|
@ -581,13 +580,13 @@ see, Guile itself is again only concerned about robustness, not about
|
||||||
correctness: without proper synchronization, your program will likely
|
correctness: without proper synchronization, your program will likely
|
||||||
not be correct, but the worst consequence is an error message.
|
not be correct, but the worst consequence is an error message.
|
||||||
|
|
||||||
Real thread-safeness often requires that a critical section of code is
|
Real thread-safety often requires that a critical section of code is
|
||||||
executed in a certain restricted manner. A common requirement is that
|
executed in a certain restricted manner. A common requirement is that
|
||||||
the code section is not entered a second time when it is already being
|
the code section is not entered a second time when it is already being
|
||||||
executed. Locking a mutex while in that section ensures that no other
|
executed. Locking a mutex while in that section ensures that no other
|
||||||
thread will start executing it, blocking asyncs ensures that no
|
thread will start executing it, blocking asyncs ensures that no
|
||||||
asynchronous code enters the section again from the current thread,
|
asynchronous code enters the section again from the current thread, and
|
||||||
and the error checking of Guile mutexes guarantees that an error is
|
the error checking of Guile mutexes guarantees that an error is
|
||||||
signalled when the current thread accidentally reenters the critical
|
signalled when the current thread accidentally reenters the critical
|
||||||
section via recursive function calls.
|
section via recursive function calls.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue