Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lock free audio #4230

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c011722
vs2022 compatible project files
LeonidGoltsblat Oct 20, 2024
81996e6
stack implementation and tests
LeonidGoltsblat Oct 20, 2024
b2ab472
code style fix
LeonidGoltsblat Oct 20, 2024
79062c1
fix to Added more logs (#4098)
LeonidGoltsblat Oct 27, 2024
267e1e0
remove Debug-Dynamic-Client and Release-Dynamic-Client configurations
LeonidGoltsblat Oct 25, 2024
79f47fb
use traditional select ioqueue instead of iocp
LeonidGoltsblat Oct 27, 2024
95f49c1
re-enabled lost stack test
LeonidGoltsblat Oct 27, 2024
97ba6f3
Merge branch 'stack' into pj_stack
LeonidGoltsblat Oct 27, 2024
24c959f
untabify
LeonidGoltsblat Oct 27, 2024
48f47a2
makefiles fixes
LeonidGoltsblat Oct 28, 2024
dd3bdc3
VS projects and solution files changes
LeonidGoltsblat Oct 28, 2024
52e0086
define appropriate PJ_POOL_ALIGNMENT for Windows platform
LeonidGoltsblat Oct 29, 2024
6a331a1
make files fix
LeonidGoltsblat Oct 29, 2024
5fec115
stack implementation files added to aconfugure.*
LeonidGoltsblat Oct 29, 2024
547b72d
merge conflicts resolved
LeonidGoltsblat Nov 24, 2024
61e69ef
merge conflicts resolved
LeonidGoltsblat Nov 24, 2024
722022d
Merge branch 'master' into pj_stack
LeonidGoltsblat Nov 24, 2024
44dd759
added some comments about data alignment and macros to control alignment
LeonidGoltsblat Nov 24, 2024
0588d57
Merge remote-tracking branch 'myfork/pj_stack' into pj_stack
LeonidGoltsblat Nov 24, 2024
f0eb2c4
stack_stress_test() added
LeonidGoltsblat Nov 26, 2024
246a20a
fix pj_stack multithreading for non-windows platforms
LeonidGoltsblat Nov 28, 2024
5db76f6
stack tests
LeonidGoltsblat Nov 29, 2024
1eea899
Merge branch 'pjsip:master' into pj_stack
LeonidGoltsblat Nov 29, 2024
37f4a8a
stack tests optimized
LeonidGoltsblat Nov 29, 2024
d7323fc
Merge branch 'pjsip:master' into pj_stack
LeonidGoltsblat Dec 3, 2024
abbad93
simplified pj_stack impl
LeonidGoltsblat Dec 8, 2024
3b0e0a4
some irreleveant changes in the patch removed
LeonidGoltsblat Dec 10, 2024
23610d6
pjlib\build\pjlib.vcxproj.filters
LeonidGoltsblat Dec 11, 2024
6fefbf5
copyright info added
LeonidGoltsblat Dec 11, 2024
6c83473
copyright 2
LeonidGoltsblat Dec 11, 2024
88e02f3
line ending
LeonidGoltsblat Dec 11, 2024
445f8a1
undone ..
LeonidGoltsblat Dec 11, 2024
9f38c20
line ending
LeonidGoltsblat Dec 12, 2024
40f57cc
rewind some unrelated changes
LeonidGoltsblat Dec 12, 2024
934ba4a
line ending
LeonidGoltsblat Dec 12, 2024
bb1307d
unrelated...
LeonidGoltsblat Dec 12, 2024
9841571
little formal changes
LeonidGoltsblat Dec 13, 2024
a102249
fix
LeonidGoltsblat Dec 13, 2024
a424e39
Merge remote-tracking branch 'github.com/master' into pj_stack
LeonidGoltsblat Dec 18, 2024
fcaa536
lock free
LeonidGoltsblat Dec 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pjlib/build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export PJLIB_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
os_time_common.o os_info.o pool.o pool_buf.o pool_caching.o pool_dbg.o \
rand.o rbtree.o sock_common.o sock_qos_common.o \
ssl_sock_common.o ssl_sock_ossl.o ssl_sock_gtls.o ssl_sock_dump.o \
ssl_sock_darwin.o string.o timer.o types.o unittest.o
ssl_sock_darwin.o stack.o string.o timer.o types.o unittest.o
export PJLIB_CFLAGS += $(_CFLAGS)
export PJLIB_CXXFLAGS += $(_CXXFLAGS)
export PJLIB_LDFLAGS += $(_LDFLAGS)
Expand All @@ -50,7 +50,7 @@ export TEST_OBJS += activesock.o atomic.o echo_clt.o errno.o exception.o \
ioq_stress_test.o ioq_unreg.o ioq_tcp.o \
list.o mutex.o os.o pool.o pool_perf.o rand.o rbtree.o \
select.o sleep.o sock.o sock_perf.o ssl_sock.o \
string.o test.o thread.o timer.o timestamp.o \
stack.o string.o test.o thread.o timer.o timestamp.o \
udp_echo_srv_sync.o udp_echo_srv_ioqueue.o \
unittest_test.o util.o
export TEST_CFLAGS += $(_CFLAGS)
Expand Down
28 changes: 28 additions & 0 deletions pjlib/build/pjlib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,33 @@
<ClCompile Include="..\src\pj\ssl_sock_ossl.c" />
<ClCompile Include="..\src\pj\ssl_sock_gtls.c" />
<ClCompile Include="..\src\pj\ssl_sock_schannel.c" />
<ClCompile Include="..\src\pj\stack.c" />
<ClCompile Include="..\src\pj\stack_win32.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug-Dynamic|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug-Dynamic|ARM'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug-Dynamic|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug-Dynamic|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug-Static|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug-Static|ARM'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug-Static|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug-Static|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release-Dynamic|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release-Dynamic|ARM'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release-Dynamic|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release-Dynamic|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release-Static|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release-Static|ARM'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release-Static|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release-Static|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\pj\string.c" />
<ClCompile Include="..\src\pj\symbols.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug-Dynamic|Win32'">true</ExcludedFromBuild>
Expand Down Expand Up @@ -1123,6 +1150,7 @@
<ClInclude Include="..\include\pj\sock_qos.h" />
<ClInclude Include="..\include\pj\sock_select.h" />
<ClInclude Include="..\include\pj\ssl_sock.h" />
<ClInclude Include="..\include\pj\stack.h" />
<ClInclude Include="..\include\pj\string.h" />
<ClInclude Include="..\include\pj\string_i.h" />
<ClInclude Include="..\include\pj\timer.h" />
Expand Down
9 changes: 9 additions & 0 deletions pjlib/build/pjlib.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,12 @@
<ClCompile Include="..\src\pj\os_rwmutex.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\pj\stack.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\pj\stack_win32.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\pj\ioqueue_common_abs.h">
Expand Down Expand Up @@ -334,6 +340,9 @@
<ClInclude Include="..\include\pj\ssl_sock.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\pj\stack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\pj\string.h">
<Filter>Header Files</Filter>
</ClInclude>
Expand Down
1 change: 1 addition & 0 deletions pjlib/build/pjlib_test.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,7 @@
<ClCompile Include="..\src\pjlib-test\sock.c" />
<ClCompile Include="..\src\pjlib-test\sock_perf.c" />
<ClCompile Include="..\src\pjlib-test\ssl_sock.c" />
<ClCompile Include="..\src\pjlib-test\stack.c" />
<ClCompile Include="..\src\pjlib-test\string.c" />
<ClCompile Include="..\src\pjlib-test\test.c" />
<ClCompile Include="..\src\pjlib-test\thread.c" />
Expand Down
3 changes: 3 additions & 0 deletions pjlib/build/pjlib_test.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@
<ClCompile Include="..\src\pjlib-test\ioq_stress_test.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\pjlib-test\stack.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\pjlib-test\test.h">
Expand Down
14 changes: 12 additions & 2 deletions pjlib/include/pj/compat/cc_gcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,18 @@

#define PJ_UNREACHED(x)

#define PJ_ALIGN_DATA(declaration, alignment) declaration __attribute__((aligned (alignment)))

/*
* Usage example:
*
* typedef struct PJ_ALIGN_DATA_PREFIX(8) a { int value; } PJ_ALIGN_DATA_SUFFIX(8) a;
* typedef struct PJ_ALIGN_DATA(a{ int value; }, 8) a;
*
* Both options are equivalent, but perhaps the first is a little more readable than the second.
*/
//#define PJ_ALIGN_DATA(declaration, alignment) declaration __attribute__((aligned (alignment)))
#define PJ_ALIGN_DATA_PREFIX(alignment)
#define PJ_ALIGN_DATA_SUFFIX(alignment) __attribute__((aligned (alignment)))
#define PJ_ALIGN_DATA(declaration, alignment) PJ_ALIGN_DATA_PREFIX(alignment) declaration PJ_ALIGN_DATA_SUFFIX(alignment)

#endif /* __PJ_COMPAT_CC_GCC_H__ */

16 changes: 14 additions & 2 deletions pjlib/include/pj/compat/cc_msvc.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,20 @@ typedef unsigned __int64 pj_uint64_t;

#define PJ_UNREACHED(x)

#define PJ_ALIGN_DATA(declaration, alignment) __declspec(align(alignment)) declaration

/*
* Usage example:
*
* typedef struct PJ_ALIGN_DATA_PREFIX(8) a { int value; } PJ_ALIGN_DATA_SUFFIX(8) a;
* typedef struct PJ_ALIGN_DATA(a{ int value; }, 8) a;
*
* Both options are equivalent, but perhaps the first is a little more readable than the second.
*/
//#define PJ_ALIGN_DATA(declaration, alignment) __declspec(align(alignment)) declaration
//#pragma warning(disable:4324) // structure padded due to align()
//#define PJ_ALIGN_DATA(declaration, alignment) __pragma(warning(push)) __pragma(warning(disable:4324)) __declspec(align(alignment)) declaration __pragma(warning(pop))
#define PJ_ALIGN_DATA_PREFIX(alignment) __pragma(warning(push)) __pragma(warning(disable:4324)) __declspec(align(alignment))
#define PJ_ALIGN_DATA_SUFFIX(alignment) __pragma(warning(pop))
#define PJ_ALIGN_DATA(declaration, alignment) PJ_ALIGN_DATA_PREFIX(alignment) declaration PJ_ALIGN_DATA_SUFFIX(alignment)

#endif /* __PJ_COMPAT_CC_MSVC_H__ */

50 changes: 50 additions & 0 deletions pjlib/include/pj/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,56 @@
# define PJ_JNI_HAS_JNI_ONLOAD PJ_ANDROID
#endif

/**
* pj_stack implementation.
* Select one of these implementations in PJ_STACK_IMPLEMENTATION.
*/
/** Using os independent "cross-platform" implementation */
#define PJ_STACK_OS_INDEPENDENT 0

/** Using Windows's single linked list */
#define PJ_STACK_WIN32 1

/**
* Select which pj_stack implementation to use. Currently pjlib supports
* PJ_STACK_OS_INDEPENDENT, which uses internal pjsip os independent
* "cross-platform" implementation, and
* PJ_STACK_WIN32, which uses Windows's single linked list.
* The last option is very fast, but requires data alignment (see below).
*
* Default is PJ_STACK_OS_INDEPENDENT.
*/
#ifndef PJ_STACK_IMPLEMENTATION
# define PJ_STACK_IMPLEMENTATION PJ_STACK_OS_INDEPENDENT
#endif

#if !defined(PJ_POOL_ALIGNMENT) && PJ_STACK_IMPLEMENTATION==PJ_STACK_WIN32
/**
* PJ_STACK_WIN32 pj_stack implementation is based on Windows single linked list and requires aligned data,
* both stack item and stack itself should be aligned by 8 (for x86) or 16 (for x64) byte.
* For this purpose winnt.h define MEMORY_ALLOCATION_ALIGNMENT as 8 for x86, ARM, ARM64 and
* 16 for x64 and ARM64EC.
* see winnt.h
*
* We need to define PJ_POOL_ALIGNMENT as MEMORY_ALLOCATION_ALIGNMENT for the Windows platform to
* dynamicaly allocate memory used by some Windows APIs.
* For example the pj_stack implementation and possibly some other implemented APIs require and check
* that PJ_POOL_ALIGNMENT is at least equal to MEMORY_ALLOCATION_ALIGNMENT,
* which is 16 on the x64 platform and 8 on the x86 platform.
*
* But it is too early to use MEMORY_ALLOCATION_ALIGNMENT constant here
* so we need to explicity declare PJ_POOL_ALIGNMENT as 8 or 16, as opposed to
* pjsip's default of 4 - see pool.h
*/
# if defined(MEMORY_ALLOCATION_ALIGNMENT)
# define PJ_POOL_ALIGNMENT MEMORY_ALLOCATION_ALIGNMENT
# elif defined(_WIN64) || defined(_M_ALPHA)
# define PJ_POOL_ALIGNMENT 16
# else
# define PJ_POOL_ALIGNMENT 8
# endif
#endif


/** @} */

Expand Down
188 changes: 188 additions & 0 deletions pjlib/include/pj/stack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/*
* Copyright (C) 2008-2024 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2022-2024 Leonid Goltsblat <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_STACK_H__
#define __PJ_STACK_H__

/**
* @file stack.h
* @brief Single Linked List data structure.
*/

#include <pj/types.h>

#if defined(PJ_STACK_IMPLEMENTATION) && PJ_STACK_IMPLEMENTATION==PJ_STACK_WIN32

/* the Windows platform stack implementation. */

/*
* PJ_STACK_ALIGN_PREFIX, PJ_STACK_ALIGN_SUFFIX is a readable syntax to declare
* platform default alignment for the stack item (see example below).
*/

# define PJ_STACK_ALIGN_PREFIX PJ_ALIGN_DATA_PREFIX(PJ_POOL_ALIGNMENT)
# define PJ_STACK_ALIGN_SUFFIX PJ_ALIGN_DATA_SUFFIX(PJ_POOL_ALIGNMENT)

#else // PJ_STACK_IMPLEMENTATION != PJ_STACK_WIN32

/* compilation of crossplatform stack implementation */

# define PJ_STACK_ALIGN_PREFIX
# define PJ_STACK_ALIGN_SUFFIX

#endif // PJ_STACK_IMPLEMENTATION


PJ_BEGIN_DECL

/*
* @defgroup PJ_DS Data Structure.
*/

/**
* @defgroup PJ_STACK Single Linked List with LIFO in/out policy
* @ingroup PJ_DS
* @{
*
* Stack in PJLIB is single-linked list with First In Last Out logic.
* Stack is thread safe. Common PJLIB stack implementation uses internal locking mechanism so is thread-safe.
* Implementation for Windows platform uses locking free Windows embeded single linked list implementation.
* The performance of pj_stack implementation for Windows platform is considerably higher than cross-platform.
*
* By default pjlib compile and link os independent "cross-platform" implementation.
* To select implementation you may optionaly define PJ_STACK_IMPLEMENTATION as PJ_STACK_WIN32
* or PJ_STACK_OS_INDEPENDENT. The last option is default.
*
* To use the implementation on the Windows platform, some prerequisites must be met:
* - this should be compiling for Windows platform
* - add #define PJ_STACK_IMPLEMENTATION PJ_STACK_WIN32
* to your config_site.h
*
* Windows single linked list implementation requires aligned data, both stack item and stack itself should
* be aligned by 8 (for x86) or 16 (for x64) byte.
* winnt.h define MEMORY_ALLOCATION_ALIGNMENT macro for this purpose.
* pjsip build system define PJ_POOL_ALIGNMENT macro to corresponding value.
* You may redefine PJ_POOL_ALIGNMENT in your config_site.h but to use PJ_STACK_WIN32 implementation
* PJ_POOL_ALIGNMENTshould not be less then MEMORY_ALLOCATION_ALIGNMENT
*
* To use MEMORY_ALLOCATION_ALIGNMENT macro in build system we recomend (this is optional) to add
* #include <windows.h> to your config_site.h.
*
* Stack won't require dynamic memory allocation (just as all PJLIB data structures). The stack here
* should be viewed more like a low level C stack instead of high level C++ stack
* (which normally are easier to use but require dynamic memory allocations),
* therefore all caveats with C stack apply here too (such as you can NOT put
* a node in more than one stacks).
*
* \section pj_stack_example_sec Examples
*
* See below for examples on how to manipulate stack:
* - @ref page_pjlib_stack_test
*/


#define IS_ALIGNED_PTR(PTR,ALIGNMENT) (((pj_ssize_t)(void*)(PTR) % (ALIGNMENT)) == 0)


/**
* Use PJ_DECL_STACK_MEMBER macro in the start of the structure declaration to
* declare that the structure can be used in the stack operation. This macro
* simply declares additional member @a next to the structure.
*
* The full declaration of stack item should contain alignment macro
* and may look like this:
*
* typedef struct PJ_STACK_ALIGN_PREFIX stack_node {
* PJ_DECL_STACK_MEMBER(struct stack_node);
* ...
* your data here
* ...
* } PJ_STACK_ALIGN_SUFFIX stack_node;
*
* @hideinitializer
*/
#define PJ_DECL_STACK_MEMBER(type) \
/** Stack @a next. */ \
type *next


/**
* Create the stack: allocate memory, allocate and initialize OS resources.
* Initially, the stack will have no member, and function pj_stack_pop() will
* always return NULL for the newly initialized stack
* (which indicates there are no any items in the stack currently).
*
* @param pool Pool to allocate memory from.
* @param stack The stack head.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_stack_create(pj_pool_t *pool, pj_stack_type **stack);

/**
* Free OS resources allocated by pj_stack_create().
*
* @param stack The target stack.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_stack_destroy(pj_stack_type *stack);


/**
* Insert (push) the node to the front of the stack as atomic (thread safe) operation.
*
* @param stack The stack.
* @param node The element to be inserted.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_stack_push(pj_stack_type *stack, pj_stack_t *node);


/**
* Extract (pop) element from the front of the stack (removing it from the stack) as atomic (thread safe) operation.
*
* @param stack The target stack.
*
* @return NULL if the stack is empty, or else pointer to element extracted from stack.
*/
PJ_DECL(pj_stack_t*) pj_stack_pop(pj_stack_type *stack);

/**
* Traverse the stack and get it's elements quantity.
* The return value of pj_stack_size should not be relied upon in multithreaded applications
* because the item count can be changed at any time by another thread.
* For Windows platform returns the number of entries in the stack modulo 65535. For example,
* if the specified stack contains 65536 entries, pj_stack_size returns zero.
*
* @param stack The target stack.
*
* @return Number of elements.
*/
PJ_DEF(pj_size_t) pj_stack_size(/*const*/ pj_stack_type *stack);


/**
* @}
*/

PJ_END_DECL

#endif /* __PJ_STACK_H__ */

Loading
Loading