2 * Copyright 2010 Piotr Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/debug.h"
31 #include "wine/exception.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(msvcp
);
35 /* error strings generated with glibc strerror */
36 static const char str_EPERM
[] = "operation not permitted";
37 static const char str_ENOENT
[] = "no such file or directory";
38 static const char str_ESRCH
[] = "no such process";
39 static const char str_EINTR
[] = "interrupted system call";
40 static const char str_EIO
[] = "input/output error";
41 static const char str_ENXIO
[] = "no such device or address";
42 static const char str_E2BIG
[] = "argument list too long";
43 static const char str_ENOEXEC
[] = "exec format error";
44 static const char str_EBADF
[] = "bad file descriptor";
45 static const char str_ECHILD
[] = "no child processes";
46 static const char str_EAGAIN
[] = "resource temporarily unavailable";
47 static const char str_ENOMEM
[] = "cannot allocate memory";
48 static const char str_EACCES
[] = "permission denied";
49 static const char str_EFAULT
[] = "bad address";
50 static const char str_EBUSY
[] = "device or resource busy";
51 static const char str_EEXIST
[] = "file exists";
52 static const char str_EXDEV
[] = "invalid cross-device link";
53 static const char str_ENODEV
[] = "no such device";
54 static const char str_ENOTDIR
[] = "not a directory";
55 static const char str_EISDIR
[] = "is a directory";
56 static const char str_EINVAL
[] = "invalid argument";
57 static const char str_ENFILE
[] = "too many open files in system";
58 static const char str_EMFILE
[] = "too many open files";
59 static const char str_ENOTTY
[] = "inappropriate ioctl for device";
60 static const char str_EFBIG
[] = "file too large";
61 static const char str_ENOSPC
[] = "no space left on device";
62 static const char str_ESPIPE
[] = "illegal seek";
63 static const char str_EROFS
[] = "read-only file system";
64 static const char str_EMLINK
[] = "too many links";
65 static const char str_EPIPE
[] = "broken pipe";
66 static const char str_EDOM
[] = "numerical argument out of domain";
67 static const char str_ERANGE
[] = "numerical result out of range";
68 static const char str_EDEADLK
[] = "resource deadlock avoided";
69 static const char str_ENAMETOOLONG
[] = "file name too long";
70 static const char str_ENOLCK
[] = "no locks available";
71 static const char str_ENOSYS
[] = "function not implemented";
72 static const char str_ENOTEMPTY
[] = "directory not empty";
73 static const char str_EILSEQ
[] = "invalid or incomplete multibyte or wide character";
74 static const char str_EADDRINUSE
[] = "address already in use";
75 static const char str_EADDRNOTAVAIL
[] = "cannot assign requested address";
76 static const char str_EAFNOSUPPORT
[] = "address family not supported by protocol";
77 static const char str_EALREADY
[] = "operation already in progress";
78 static const char str_EBADMSG
[] = "not a data message";
79 static const char str_ECANCELED
[] = "operation Canceled";
80 static const char str_ECONNABORTED
[] = "software caused connection abort";
81 static const char str_ECONNREFUSED
[] = "connection refused";
82 static const char str_ECONNRESET
[] = "connection reset by peer";
83 static const char str_EDESTADDRREQ
[] = "destination address required";
84 static const char str_EHOSTUNREACH
[] = "no route to host";
85 static const char str_EIDRM
[] = "identifier removed";
86 static const char str_EINPROGRESS
[] = "operation now in progress";
87 static const char str_EISCONN
[] = "transport endpoint is already connected";
88 static const char str_ELOOP
[] = "too many symbolic links encountered";
89 static const char str_EMSGSIZE
[] = "message too long";
90 static const char str_ENETDOWN
[] = "network is down";
91 static const char str_ENETRESET
[] = "network dropped connection because of reset";
92 static const char str_ENETUNREACH
[] = "network is unreachable";
93 static const char str_ENOBUFS
[] = "no buffer space available";
94 static const char str_ENODATA
[] = "no data available";
95 static const char str_ENOLINK
[] = "link has been severed";
96 static const char str_ENOMSG
[] = "no message of desired type";
97 static const char str_ENOPROTOOPT
[] = "protocol not available";
98 static const char str_ENOSR
[] = "out of streams resources";
99 static const char str_ENOSTR
[] = "device not a stream";
100 static const char str_ENOTCONN
[] = "transport endpoint is not connected";
101 static const char str_ENOTRECOVERABLE
[] = "state not recoverable";
102 static const char str_ENOTSOCK
[] = "socket operation on non-socket";
103 static const char str_ENOTSUP
[] = "not supported";
104 static const char str_EOPNOTSUPP
[] = "operation not supported on transport endpoint";
105 static const char str_EOVERFLOW
[] = "value too large for defined data type";
106 static const char str_EOWNERDEAD
[] = "owner died";
107 static const char str_EPROTO
[] = "protocol error";
108 static const char str_EPROTONOSUPPORT
[] = "protocol not supported";
109 static const char str_EPROTOTYPE
[] = "protocol wrong type for socket";
110 static const char str_ETIME
[] = "timer expired";
111 static const char str_ETIMEDOUT
[] = "connection timed out";
112 static const char str_ETXTBSY
[] = "text file busy";
113 static const char str_EWOULDBLOCK
[] = "operation would block";
121 {ENOENT
, str_ENOENT
},
127 {ENOEXEC
, str_ENOEXEC
},
129 {ECHILD
, str_ECHILD
},
130 {EAGAIN
, str_EAGAIN
},
131 {ENOMEM
, str_ENOMEM
},
132 {EACCES
, str_EACCES
},
133 {EFAULT
, str_EFAULT
},
135 {EEXIST
, str_EEXIST
},
137 {ENODEV
, str_ENODEV
},
138 {ENOTDIR
, str_ENOTDIR
},
139 {EISDIR
, str_EISDIR
},
140 {EINVAL
, str_EINVAL
},
141 {ENFILE
, str_ENFILE
},
142 {EMFILE
, str_EMFILE
},
143 {ENOTTY
, str_ENOTTY
},
145 {ENOSPC
, str_ENOSPC
},
146 {ESPIPE
, str_ESPIPE
},
148 {EMLINK
, str_EMLINK
},
151 {ERANGE
, str_ERANGE
},
152 {EDEADLK
, str_EDEADLK
},
153 {ENAMETOOLONG
, str_ENAMETOOLONG
},
154 {ENOLCK
, str_ENOLCK
},
155 {ENOSYS
, str_ENOSYS
},
156 {ENOTEMPTY
, str_ENOTEMPTY
},
157 {EILSEQ
, str_EILSEQ
},
158 {EADDRINUSE
, str_EADDRINUSE
},
159 {EADDRNOTAVAIL
, str_EADDRNOTAVAIL
},
160 {EAFNOSUPPORT
, str_EAFNOSUPPORT
},
161 {EALREADY
, str_EALREADY
},
162 {EBADMSG
, str_EBADMSG
},
163 {ECANCELED
, str_ECANCELED
},
164 {ECONNABORTED
, str_ECONNABORTED
},
165 {ECONNREFUSED
, str_ECONNREFUSED
},
166 {ECONNRESET
, str_ECONNRESET
},
167 {EDESTADDRREQ
, str_EDESTADDRREQ
},
168 {EHOSTUNREACH
, str_EHOSTUNREACH
},
170 {EINPROGRESS
, str_EINPROGRESS
},
171 {EISCONN
, str_EISCONN
},
173 {EMSGSIZE
, str_EMSGSIZE
},
174 {ENETDOWN
, str_ENETDOWN
},
175 {ENETRESET
, str_ENETRESET
},
176 {ENETUNREACH
, str_ENETUNREACH
},
177 {ENOBUFS
, str_ENOBUFS
},
178 {ENODATA
, str_ENODATA
},
179 {ENOLINK
, str_ENOLINK
},
180 {ENOMSG
, str_ENOMSG
},
181 {ENOPROTOOPT
, str_ENOPROTOOPT
},
183 {ENOSTR
, str_ENOSTR
},
184 {ENOTCONN
, str_ENOTCONN
},
185 {ENOTRECOVERABLE
, str_ENOTRECOVERABLE
},
186 {ENOTSOCK
, str_ENOTSOCK
},
187 {ENOTSUP
, str_ENOTSUP
},
188 {EOPNOTSUPP
, str_EOPNOTSUPP
},
189 {EOVERFLOW
, str_EOVERFLOW
},
190 {EOWNERDEAD
, str_EOWNERDEAD
},
191 {EPROTO
, str_EPROTO
},
192 {EPROTONOSUPPORT
, str_EPROTONOSUPPORT
},
193 {EPROTOTYPE
, str_EPROTOTYPE
},
195 {ETIMEDOUT
, str_ETIMEDOUT
},
196 {ETXTBSY
, str_ETXTBSY
},
197 {EWOULDBLOCK
, str_EWOULDBLOCK
},
201 #if _MSVCP_VER >= 140
207 {ERROR_INVALID_FUNCTION
, ENOSYS
}, {ERROR_FILE_NOT_FOUND
, ENOENT
},
208 {ERROR_PATH_NOT_FOUND
, ENOENT
}, {ERROR_TOO_MANY_OPEN_FILES
, EMFILE
},
209 {ERROR_ACCESS_DENIED
, EACCES
}, {ERROR_INVALID_HANDLE
, EINVAL
},
210 {ERROR_NOT_ENOUGH_MEMORY
, ENOMEM
}, {ERROR_INVALID_ACCESS
, EACCES
},
211 {ERROR_OUTOFMEMORY
, ENOMEM
}, {ERROR_INVALID_DRIVE
, ENODEV
},
212 {ERROR_CURRENT_DIRECTORY
, EACCES
}, {ERROR_NOT_SAME_DEVICE
, EXDEV
},
213 {ERROR_WRITE_PROTECT
, EACCES
}, {ERROR_BAD_UNIT
, ENODEV
},
214 {ERROR_NOT_READY
, EAGAIN
}, {ERROR_SEEK
, EIO
}, {ERROR_WRITE_FAULT
, EIO
},
215 {ERROR_READ_FAULT
, EIO
}, {ERROR_SHARING_VIOLATION
, EACCES
},
216 {ERROR_LOCK_VIOLATION
, ENOLCK
}, {ERROR_HANDLE_DISK_FULL
, ENOSPC
},
217 {ERROR_NOT_SUPPORTED
, ENOTSUP
}, {ERROR_DEV_NOT_EXIST
, ENODEV
},
218 {ERROR_FILE_EXISTS
, EEXIST
}, {ERROR_CANNOT_MAKE
, EACCES
},
219 {ERROR_INVALID_PARAMETER
, EINVAL
}, {ERROR_OPEN_FAILED
, EIO
},
220 {ERROR_BUFFER_OVERFLOW
, ENAMETOOLONG
}, {ERROR_DISK_FULL
, ENOSPC
},
221 {ERROR_INVALID_NAME
, EINVAL
}, {ERROR_NEGATIVE_SEEK
, EINVAL
},
222 {ERROR_BUSY_DRIVE
, EBUSY
}, {ERROR_DIR_NOT_EMPTY
, ENOTEMPTY
},
223 {ERROR_BUSY
, EBUSY
}, {ERROR_ALREADY_EXISTS
, EEXIST
},
224 {ERROR_LOCKED
, ENOLCK
}, {ERROR_DIRECTORY
, EINVAL
},
225 {ERROR_OPERATION_ABORTED
, ECANCELED
}, {ERROR_NOACCESS
, EACCES
},
226 {ERROR_CANTOPEN
, EIO
}, {ERROR_CANTREAD
, EIO
}, {ERROR_CANTWRITE
, EIO
},
227 {ERROR_RETRY
, EAGAIN
}, {ERROR_OPEN_FILES
, EBUSY
},
228 {ERROR_DEVICE_IN_USE
, EBUSY
}, {ERROR_REPARSE_TAG_INVALID
, EINVAL
},
229 {WSAEINTR
, EINTR
}, {WSAEBADF
, EBADF
}, {WSAEACCES
, EACCES
},
230 {WSAEFAULT
, EFAULT
}, {WSAEINVAL
, EINVAL
}, {WSAEMFILE
, EMFILE
},
231 {WSAEWOULDBLOCK
, EWOULDBLOCK
}, {WSAEINPROGRESS
, EINPROGRESS
},
232 {WSAEALREADY
, EALREADY
}, {WSAENOTSOCK
, ENOTSOCK
},
233 {WSAEDESTADDRREQ
, EDESTADDRREQ
}, {WSAEMSGSIZE
, EMSGSIZE
},
234 {WSAEPROTOTYPE
, EPROTOTYPE
}, {WSAENOPROTOOPT
, ENOPROTOOPT
},
235 {WSAEPROTONOSUPPORT
, EPROTONOSUPPORT
}, {WSAEOPNOTSUPP
, EOPNOTSUPP
},
236 {WSAEAFNOSUPPORT
, EAFNOSUPPORT
}, {WSAEADDRINUSE
, EADDRINUSE
},
237 {WSAEADDRNOTAVAIL
, EADDRNOTAVAIL
}, {WSAENETDOWN
, ENETDOWN
},
238 {WSAENETUNREACH
, ENETUNREACH
}, {WSAENETRESET
, ENETRESET
},
239 {WSAECONNABORTED
, ECONNABORTED
}, {WSAECONNRESET
, ECONNRESET
},
240 {WSAENOBUFS
, ENOBUFS
}, {WSAEISCONN
, EISCONN
}, {WSAENOTCONN
, ENOTCONN
},
241 {WSAETIMEDOUT
, ETIMEDOUT
}, {WSAECONNREFUSED
, ECONNREFUSED
},
242 {WSAENAMETOOLONG
, ENAMETOOLONG
}, {WSAEHOSTUNREACH
, EHOSTUNREACH
}
246 struct __Container_proxy
;
249 struct __Container_proxy
*proxy
;
252 typedef struct __Iterator_base12
{
253 struct __Container_proxy
*proxy
;
254 struct __Iterator_base12
*next
;
257 typedef struct __Container_proxy
{
258 const _Container_base12
*cont
;
259 _Iterator_base12
*head
;
262 /* ??0_Mutex@std@@QAE@XZ */
263 /* ??0_Mutex@std@@QEAA@XZ */
264 DEFINE_THISCALL_WRAPPER(mutex_ctor
, 4)
265 mutex
* __thiscall
mutex_ctor(mutex
*this)
267 CRITICAL_SECTION
*cs
= MSVCRT_operator_new(sizeof(*cs
));
269 ERR("Out of memory\n");
270 throw_exception(EXCEPTION_BAD_ALLOC
, NULL
);
273 InitializeCriticalSection(cs
);
274 cs
->DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": _Mutex critical section");
279 /* ??1_Mutex@std@@QAE@XZ */
280 /* ??1_Mutex@std@@QEAA@XZ */
281 DEFINE_THISCALL_WRAPPER(mutex_dtor
, 4)
282 void __thiscall
mutex_dtor(mutex
*this)
284 ((CRITICAL_SECTION
*)this->mutex
)->DebugInfo
->Spare
[0] = 0;
285 DeleteCriticalSection(this->mutex
);
286 MSVCRT_operator_delete(this->mutex
);
289 /* ?_Lock@_Mutex@std@@QAEXXZ */
290 /* ?_Lock@_Mutex@std@@QEAAXXZ */
291 DEFINE_THISCALL_WRAPPER(mutex_lock
, 4)
292 void __thiscall
mutex_lock(mutex
*this)
294 EnterCriticalSection(this->mutex
);
297 /* ?_Unlock@_Mutex@std@@QAEXXZ */
298 /* ?_Unlock@_Mutex@std@@QEAAXXZ */
299 DEFINE_THISCALL_WRAPPER(mutex_unlock
, 4)
300 void __thiscall
mutex_unlock(mutex
*this)
302 LeaveCriticalSection(this->mutex
);
305 /* ?_Mutex_Lock@_Mutex@std@@CAXPAV12@@Z */
306 /* ?_Mutex_Lock@_Mutex@std@@CAXPEAV12@@Z */
307 void CDECL
mutex_mutex_lock(mutex
*m
)
312 /* ?_Mutex_Unlock@_Mutex@std@@CAXPAV12@@Z */
313 /* ?_Mutex_Unlock@_Mutex@std@@CAXPEAV12@@Z */
314 void CDECL
mutex_mutex_unlock(mutex
*m
)
319 /* ?_Mutex_ctor@_Mutex@std@@CAXPAV12@@Z */
320 /* ?_Mutex_ctor@_Mutex@std@@CAXPEAV12@@Z */
321 void CDECL
mutex_mutex_ctor(mutex
*m
)
326 /* ?_Mutex_dtor@_Mutex@std@@CAXPAV12@@Z */
327 /* ?_Mutex_dtor@_Mutex@std@@CAXPEAV12@@Z */
328 void CDECL
mutex_mutex_dtor(mutex
*m
)
333 static CRITICAL_SECTION lockit_cs
[_MAX_LOCK
];
336 static inline int get_locktype( _Lockit
*lockit
) { return lockit
->locktype
; }
337 static inline void set_locktype( _Lockit
*lockit
, int type
) { lockit
->locktype
= type
; }
339 static inline int get_locktype( _Lockit
*lockit
) { return 0; }
340 static inline void set_locktype( _Lockit
*lockit
, int type
) { }
343 /* ?_Lockit_ctor@_Lockit@std@@SAXH@Z */
344 void __cdecl
_Lockit_init(int locktype
) {
345 InitializeCriticalSection(&lockit_cs
[locktype
]);
346 lockit_cs
[locktype
].DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": _Lockit critical section");
349 /* ?_Lockit_dtor@_Lockit@std@@SAXH@Z */
350 void __cdecl
_Lockit_free(int locktype
)
352 lockit_cs
[locktype
].DebugInfo
->Spare
[0] = 0;
353 DeleteCriticalSection(&lockit_cs
[locktype
]);
356 void init_lockit(void) {
359 for(i
=0; i
<_MAX_LOCK
; i
++)
363 void free_lockit(void) {
366 for(i
=0; i
<_MAX_LOCK
; i
++)
370 /* ?_Lockit_ctor@_Lockit@std@@CAXPAV12@H@Z */
371 /* ?_Lockit_ctor@_Lockit@std@@CAXPEAV12@H@Z */
372 void __cdecl
_Lockit__Lockit_ctor_locktype(_Lockit
*lockit
, int locktype
)
374 set_locktype( lockit
, locktype
);
375 EnterCriticalSection(&lockit_cs
[locktype
]);
378 /* ?_Lockit_ctor@_Lockit@std@@CAXPAV12@@Z */
379 /* ?_Lockit_ctor@_Lockit@std@@CAXPEAV12@@Z */
380 void __cdecl
_Lockit__Lockit_ctor(_Lockit
*lockit
)
382 _Lockit__Lockit_ctor_locktype(lockit
, 0);
385 /* ??0_Lockit@std@@QAE@H@Z */
386 /* ??0_Lockit@std@@QEAA@H@Z */
387 DEFINE_THISCALL_WRAPPER(_Lockit_ctor_locktype
, 8)
388 _Lockit
* __thiscall
_Lockit_ctor_locktype(_Lockit
*this, int locktype
)
390 _Lockit__Lockit_ctor_locktype(this, locktype
);
394 /* ??0_Lockit@std@@QAE@XZ */
395 /* ??0_Lockit@std@@QEAA@XZ */
396 DEFINE_THISCALL_WRAPPER(_Lockit_ctor
, 4)
397 _Lockit
* __thiscall
_Lockit_ctor(_Lockit
*this)
399 _Lockit__Lockit_ctor_locktype(this, 0);
403 /* ?_Lockit_dtor@_Lockit@std@@CAXPAV12@@Z */
404 /* ?_Lockit_dtor@_Lockit@std@@CAXPEAV12@@Z */
405 void __cdecl
_Lockit__Lockit_dtor(_Lockit
*lockit
)
407 LeaveCriticalSection(&lockit_cs
[get_locktype( lockit
)]);
410 /* ??1_Lockit@std@@QAE@XZ */
411 /* ??1_Lockit@std@@QEAA@XZ */
412 DEFINE_THISCALL_WRAPPER(_Lockit_dtor
, 4)
413 void __thiscall
_Lockit_dtor(_Lockit
*this)
415 _Lockit__Lockit_dtor(this);
419 unsigned short __cdecl
wctype(const char *property
)
421 static const struct {
425 { "alnum", _DIGIT
|_ALPHA
},
427 { "cntrl", _CONTROL
},
429 { "graph", _DIGIT
|_PUNCT
|_ALPHA
},
431 { "print", _DIGIT
|_PUNCT
|_BLANK
|_ALPHA
},
439 for(i
= 0; i
< ARRAY_SIZE(properties
); i
++)
440 if(!strcmp(property
, properties
[i
].name
))
441 return properties
[i
].mask
;
446 typedef void (__cdecl
*MSVCP_new_handler_func
)(void);
447 static MSVCP_new_handler_func MSVCP_new_handler
;
448 static int __cdecl
new_handler_wrapper(MSVCP_size_t unused
)
454 /* ?set_new_handler@std@@YAP6AXXZP6AXXZ@Z */
455 MSVCP_new_handler_func __cdecl
set_new_handler(MSVCP_new_handler_func new_handler
)
457 MSVCP_new_handler_func old_handler
= MSVCP_new_handler
;
459 TRACE("%p\n", new_handler
);
461 MSVCP_new_handler
= new_handler
;
462 MSVCRT_set_new_handler(new_handler
? new_handler_wrapper
: NULL
);
466 /* ?set_new_handler@std@@YAP6AXXZH@Z */
467 MSVCP_new_handler_func __cdecl
set_new_handler_reset(int unused
)
469 return set_new_handler(NULL
);
472 /* _Container_base0 is used by apps compiled without iterator checking
473 * (i.e. with _ITERATOR_DEBUG_LEVEL=0 ).
474 * It provides empty versions of methods used by visual c++'s stl's
476 * msvcr100 has to provide them in case apps are compiled with /Od
477 * or the optimizer fails to inline those (empty) calls.
480 /* ?_Orphan_all@_Container_base0@std@@QAEXXZ */
481 /* ?_Orphan_all@_Container_base0@std@@QEAAXXZ */
482 DEFINE_THISCALL_WRAPPER(Container_base0_Orphan_all
, 4)
483 void __thiscall
Container_base0_Orphan_all(void *this)
487 /* ?_Swap_all@_Container_base0@std@@QAEXAAU12@@Z */
488 /* ?_Swap_all@_Container_base0@std@@QEAAXAEAU12@@Z */
489 DEFINE_THISCALL_WRAPPER(Container_base0_Swap_all
, 8)
490 void __thiscall
Container_base0_Swap_all(void *this, void *that
)
494 /* ??4_Container_base0@std@@QAEAAU01@ABU01@@Z */
495 /* ??4_Container_base0@std@@QEAAAEAU01@AEBU01@@Z */
496 DEFINE_THISCALL_WRAPPER(Container_base0_op_assign
, 8)
497 void* __thiscall
Container_base0_op_assign(void *this, const void *that
)
502 /* ??0_Container_base12@std@@QAE@ABU01@@Z */
503 /* ??0_Container_base12@std@@QEAA@AEBU01@@Z */
504 DEFINE_THISCALL_WRAPPER(_Container_base12_copy_ctor
, 8)
505 _Container_base12
* __thiscall
_Container_base12_copy_ctor(
506 _Container_base12
*this, _Container_base12
*that
)
512 /* ??0_Container_base12@std@@QAE@XZ */
513 /* ??0_Container_base12@std@@QEAA@XZ */
514 DEFINE_THISCALL_WRAPPER(_Container_base12_ctor
, 4)
515 _Container_base12
* __thiscall
_Container_base12_ctor(_Container_base12
*this)
521 /* ??1_Container_base12@std@@QAE@XZ */
522 /* ??1_Container_base12@std@@QEAA@XZ */
523 DEFINE_THISCALL_WRAPPER(_Container_base12_dtor
, 4)
524 void __thiscall
_Container_base12_dtor(_Container_base12
*this)
528 /* ??4_Container_base12@std@@QAEAAU01@ABU01@@Z */
529 /* ??4_Container_base12@std@@QEAAAEAU01@AEBU01@@ */
530 DEFINE_THISCALL_WRAPPER(_Container_base12_op_assign
, 8)
531 _Container_base12
* __thiscall
_Container_base12_op_assign(
532 _Container_base12
*this, const _Container_base12
*that
)
537 /* ?_Getpfirst@_Container_base12@std@@QBEPAPAU_Iterator_base12@2@XZ */
538 /* ?_Getpfirst@_Container_base12@std@@QEBAPEAPEAU_Iterator_base12@2@XZ */
539 DEFINE_THISCALL_WRAPPER(_Container_base12__Getpfirst
, 4)
540 _Iterator_base12
** __thiscall
_Container_base12__Getpfirst(_Container_base12
*this)
542 return this->proxy
? &this->proxy
->head
: NULL
;
545 /* ?_Orphan_all@_Container_base12@std@@QAEXXZ */
546 /* ?_Orphan_all@_Container_base12@std@@QEAAXXZ */
547 DEFINE_THISCALL_WRAPPER(_Container_base12__Orphan_all
, 4)
548 void __thiscall
_Container_base12__Orphan_all(_Container_base12
*this)
552 /* ?_Swap_all@_Container_base12@std@@QAEXAAU12@@Z */
553 /* ?_Swap_all@_Container_base12@std@@QEAAXAEAU12@@Z */
554 DEFINE_THISCALL_WRAPPER(_Container_base12__Swap_all
, 8)
555 void __thiscall
_Container_base12__Swap_all(
556 _Container_base12
*this, _Container_base12
*that
)
558 _Container_proxy
*tmp
;
561 this->proxy
= that
->proxy
;
565 this->proxy
->cont
= this;
567 that
->proxy
->cont
= that
;
570 #if _MSVCP_VER >= 110
572 #define SECSPERDAY 86400
573 /* 1601 to 1970 is 369 years plus 89 leap days */
574 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
575 #define TICKSPERSEC 10000000
576 #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
577 #define NANOSEC_PER_MILLISEC 1000000
578 #define MILLISEC_PER_SEC 1000
579 #define NANOSEC_PER_SEC (NANOSEC_PER_MILLISEC * MILLISEC_PER_SEC)
581 typedef int MSVCRT_long
;
589 /* _Xtime_get_ticks */
590 LONGLONG __cdecl
_Xtime_get_ticks(void)
596 GetSystemTimeAsFileTime(&ft
);
597 return ((LONGLONG
)ft
.dwHighDateTime
<<32) + ft
.dwLowDateTime
- TICKS_1601_TO_1970
;
601 int __cdecl
xtime_get(xtime
* t
, int unknown
)
610 ticks
= _Xtime_get_ticks();
611 t
->sec
= ticks
/ TICKSPERSEC
;
612 t
->nsec
= ticks
% TICKSPERSEC
* 100;
616 /* _Xtime_diff_to_millis2 */
617 MSVCRT_long __cdecl
_Xtime_diff_to_millis2(const xtime
*t1
, const xtime
*t2
)
619 LONGLONG diff_sec
, diff_nsec
;
621 TRACE("(%p, %p)\n", t1
, t2
);
623 diff_sec
= t1
->sec
- t2
->sec
;
624 diff_nsec
= t1
->nsec
- t2
->nsec
;
626 diff_sec
+= diff_nsec
/ NANOSEC_PER_SEC
;
627 diff_nsec
%= NANOSEC_PER_SEC
;
630 diff_nsec
+= NANOSEC_PER_SEC
;
633 if (diff_sec
<0 || (diff_sec
==0 && diff_nsec
<0))
635 return diff_sec
* MILLISEC_PER_SEC
+
636 (diff_nsec
+ NANOSEC_PER_MILLISEC
- 1) / NANOSEC_PER_MILLISEC
;
639 /* _Xtime_diff_to_millis */
640 MSVCRT_long __cdecl
_Xtime_diff_to_millis(const xtime
*t
)
647 return _Xtime_diff_to_millis2(t
, &now
);
652 unsigned int __cdecl
_Random_device(void)
658 /* TODO: throw correct exception in case of failure */
660 throw_exception(EXCEPTION
, "random number generator failed\n");
665 #if _MSVCP_VER >= 110
666 #if defined(__i386__)
668 extern void *call_thiscall_func
;
669 __ASM_GLOBAL_FUNC(call_thiscall_func
,
676 #define call_func1(func,this) ((void* (WINAPI*)(void*,void*))&call_thiscall_func)(func,this)
680 #define call_func1(func,this) func(this)
682 #endif /* __i386__ */
684 #define MTX_MULTI_LOCK 0x100
694 #if _MSVCP_VER >= 140
695 typedef _Mtx_t _Mtx_arg_t
;
696 #define MTX_T_FROM_ARG(m) (m)
697 #define MTX_T_TO_ARG(m) (m)
699 typedef _Mtx_t
*_Mtx_arg_t
;
700 #define MTX_T_FROM_ARG(m) (*(m))
701 #define MTX_T_TO_ARG(m) (&(m))
704 void __cdecl
_Mtx_init_in_situ(_Mtx_t mtx
, int flags
)
706 if(flags
& ~MTX_MULTI_LOCK
)
707 FIXME("unknown flags ignored: %x\n", flags
);
710 call_func1(critical_section_ctor
, &mtx
->cs
);
715 int __cdecl
_Mtx_init(_Mtx_t
*mtx
, int flags
)
717 *mtx
= MSVCRT_operator_new(sizeof(**mtx
));
718 _Mtx_init_in_situ(*mtx
, flags
);
722 void __cdecl
_Mtx_destroy_in_situ(_Mtx_t mtx
)
724 call_func1(critical_section_dtor
, &mtx
->cs
);
727 void __cdecl
_Mtx_destroy(_Mtx_arg_t mtx
)
729 call_func1(critical_section_dtor
, &MTX_T_FROM_ARG(mtx
)->cs
);
730 MSVCRT_operator_delete(MTX_T_FROM_ARG(mtx
));
733 int __cdecl
_Mtx_current_owns(_Mtx_arg_t mtx
)
735 return MTX_T_FROM_ARG(mtx
)->thread_id
== GetCurrentThreadId();
738 int __cdecl
_Mtx_lock(_Mtx_arg_t mtx
)
740 if(MTX_T_FROM_ARG(mtx
)->thread_id
!= GetCurrentThreadId()) {
741 call_func1(critical_section_lock
, &MTX_T_FROM_ARG(mtx
)->cs
);
742 MTX_T_FROM_ARG(mtx
)->thread_id
= GetCurrentThreadId();
743 }else if(!(MTX_T_FROM_ARG(mtx
)->flags
& MTX_MULTI_LOCK
)) {
747 MTX_T_FROM_ARG(mtx
)->count
++;
751 int __cdecl
_Mtx_unlock(_Mtx_arg_t mtx
)
753 if(--MTX_T_FROM_ARG(mtx
)->count
)
756 MTX_T_FROM_ARG(mtx
)->thread_id
= -1;
757 call_func1(critical_section_unlock
, &MTX_T_FROM_ARG(mtx
)->cs
);
761 int __cdecl
_Mtx_trylock(_Mtx_arg_t mtx
)
763 if(MTX_T_FROM_ARG(mtx
)->thread_id
!= GetCurrentThreadId()) {
764 if(!call_func1(critical_section_trylock
, &MTX_T_FROM_ARG(mtx
)->cs
))
766 MTX_T_FROM_ARG(mtx
)->thread_id
= GetCurrentThreadId();
767 }else if(!(MTX_T_FROM_ARG(mtx
)->flags
& MTX_MULTI_LOCK
)) {
771 MTX_T_FROM_ARG(mtx
)->count
++;
775 critical_section
* __cdecl
_Mtx_getconcrtcs(_Mtx_arg_t mtx
)
777 return &MTX_T_FROM_ARG(mtx
)->cs
;
780 static inline LONG
interlocked_dec_if_nonzero( LONG
*dest
)
783 for (val
= *dest
;; val
= tmp
)
785 if (!val
|| (tmp
= InterlockedCompareExchange( dest
, val
- 1, val
)) == val
)
791 #define CND_TIMEDOUT 2
795 CONDITION_VARIABLE cv
;
798 #if _MSVCP_VER >= 140
799 typedef _Cnd_t _Cnd_arg_t
;
800 #define CND_T_FROM_ARG(c) (c)
801 #define CND_T_TO_ARG(c) (c)
803 typedef _Cnd_t
*_Cnd_arg_t
;
804 #define CND_T_FROM_ARG(c) (*(c))
805 #define CND_T_TO_ARG(c) (&(c))
808 static HANDLE keyed_event
;
810 void __cdecl
_Cnd_init_in_situ(_Cnd_t cnd
)
812 InitializeConditionVariable(&cnd
->cv
);
817 NtCreateKeyedEvent(&event
, GENERIC_READ
|GENERIC_WRITE
, NULL
, 0);
818 if(InterlockedCompareExchangePointer(&keyed_event
, event
, NULL
) != NULL
)
823 int __cdecl
_Cnd_init(_Cnd_t
*cnd
)
825 *cnd
= MSVCRT_operator_new(sizeof(**cnd
));
826 _Cnd_init_in_situ(*cnd
);
830 int __cdecl
_Cnd_wait(_Cnd_arg_t cnd
, _Mtx_arg_t mtx
)
832 CONDITION_VARIABLE
*cv
= &CND_T_FROM_ARG(cnd
)->cv
;
834 InterlockedExchangeAdd( (LONG
*)&cv
->Ptr
, 1 );
837 NtWaitForKeyedEvent(keyed_event
, &cv
->Ptr
, FALSE
, NULL
);
843 int __cdecl
_Cnd_timedwait(_Cnd_arg_t cnd
, _Mtx_arg_t mtx
, const xtime
*xt
)
845 CONDITION_VARIABLE
*cv
= &CND_T_FROM_ARG(cnd
)->cv
;
846 LARGE_INTEGER timeout
;
849 InterlockedExchangeAdd( (LONG
*)&cv
->Ptr
, 1 );
852 timeout
.QuadPart
= (ULONGLONG
)(ULONG
)_Xtime_diff_to_millis(xt
) * -10000;
853 status
= NtWaitForKeyedEvent(keyed_event
, &cv
->Ptr
, FALSE
, &timeout
);
856 if (!interlocked_dec_if_nonzero( (LONG
*)&cv
->Ptr
))
857 status
= NtWaitForKeyedEvent( keyed_event
, &cv
->Ptr
, FALSE
, NULL
);
861 return status
? CND_TIMEDOUT
: 0;
864 int __cdecl
_Cnd_broadcast(_Cnd_arg_t cnd
)
866 CONDITION_VARIABLE
*cv
= &CND_T_FROM_ARG(cnd
)->cv
;
867 LONG val
= InterlockedExchange( (LONG
*)&cv
->Ptr
, 0 );
869 NtReleaseKeyedEvent( keyed_event
, &cv
->Ptr
, FALSE
, NULL
);
873 int __cdecl
_Cnd_signal(_Cnd_arg_t cnd
)
875 CONDITION_VARIABLE
*cv
= &CND_T_FROM_ARG(cnd
)->cv
;
876 if (interlocked_dec_if_nonzero( (LONG
*)&cv
->Ptr
))
877 NtReleaseKeyedEvent( keyed_event
, &cv
->Ptr
, FALSE
, NULL
);
881 void __cdecl
_Cnd_destroy_in_situ(_Cnd_t cnd
)
883 _Cnd_broadcast(CND_T_TO_ARG(cnd
));
886 void __cdecl
_Cnd_destroy(_Cnd_arg_t cnd
)
890 MSVCRT_operator_delete(CND_T_FROM_ARG(cnd
));
898 struct _to_broadcast
{
904 } broadcast_at_thread_exit
;
906 static CRITICAL_SECTION broadcast_at_thread_exit_cs
;
907 static CRITICAL_SECTION_DEBUG broadcast_at_thread_exit_cs_debug
=
909 0, 0, &broadcast_at_thread_exit_cs
,
910 { &broadcast_at_thread_exit_cs_debug
.ProcessLocksList
, &broadcast_at_thread_exit_cs_debug
.ProcessLocksList
},
911 0, 0, { (DWORD_PTR
)(__FILE__
": broadcast_at_thread_exit_cs") }
913 static CRITICAL_SECTION broadcast_at_thread_exit_cs
= { &broadcast_at_thread_exit_cs_debug
, -1, 0, 0, 0, 0 };
915 void __cdecl
_Cnd_register_at_thread_exit(_Cnd_arg_t cnd
, _Mtx_arg_t mtx
, int *p
)
917 struct _to_broadcast
*add
;
919 TRACE("(%p %p %p)\n", cnd
, mtx
, p
);
921 EnterCriticalSection(&broadcast_at_thread_exit_cs
);
922 if(!broadcast_at_thread_exit
.size
) {
923 broadcast_at_thread_exit
.to_broadcast
= HeapAlloc(GetProcessHeap(),
924 0, 8*sizeof(broadcast_at_thread_exit
.to_broadcast
[0]));
925 if(!broadcast_at_thread_exit
.to_broadcast
) {
926 LeaveCriticalSection(&broadcast_at_thread_exit_cs
);
929 broadcast_at_thread_exit
.size
= 8;
930 } else if(broadcast_at_thread_exit
.size
== broadcast_at_thread_exit
.used
) {
931 add
= HeapReAlloc(GetProcessHeap(), 0, broadcast_at_thread_exit
.to_broadcast
,
932 broadcast_at_thread_exit
.size
*2*sizeof(broadcast_at_thread_exit
.to_broadcast
[0]));
934 LeaveCriticalSection(&broadcast_at_thread_exit_cs
);
937 broadcast_at_thread_exit
.to_broadcast
= add
;
938 broadcast_at_thread_exit
.size
*= 2;
941 add
= broadcast_at_thread_exit
.to_broadcast
+ broadcast_at_thread_exit
.used
++;
942 add
->thread_id
= GetCurrentThreadId();
946 LeaveCriticalSection(&broadcast_at_thread_exit_cs
);
949 void __cdecl
_Cnd_unregister_at_thread_exit(_Mtx_arg_t mtx
)
953 TRACE("(%p)\n", mtx
);
955 EnterCriticalSection(&broadcast_at_thread_exit_cs
);
956 for(i
=0; i
<broadcast_at_thread_exit
.used
; i
++) {
957 if(broadcast_at_thread_exit
.to_broadcast
[i
].mtx
!= mtx
)
960 memmove(broadcast_at_thread_exit
.to_broadcast
+i
, broadcast_at_thread_exit
.to_broadcast
+i
+1,
961 (broadcast_at_thread_exit
.used
-i
-1)*sizeof(broadcast_at_thread_exit
.to_broadcast
[0]));
962 broadcast_at_thread_exit
.used
--;
965 LeaveCriticalSection(&broadcast_at_thread_exit_cs
);
968 void __cdecl
_Cnd_do_broadcast_at_thread_exit(void)
970 int i
, id
= GetCurrentThreadId();
974 EnterCriticalSection(&broadcast_at_thread_exit_cs
);
975 for(i
=0; i
<broadcast_at_thread_exit
.used
; i
++) {
976 if(broadcast_at_thread_exit
.to_broadcast
[i
].thread_id
!= id
)
979 _Mtx_unlock(broadcast_at_thread_exit
.to_broadcast
[i
].mtx
);
980 _Cnd_broadcast(broadcast_at_thread_exit
.to_broadcast
[i
].cnd
);
981 if(broadcast_at_thread_exit
.to_broadcast
[i
].p
)
982 *broadcast_at_thread_exit
.to_broadcast
[i
].p
= 1;
984 memmove(broadcast_at_thread_exit
.to_broadcast
+i
, broadcast_at_thread_exit
.to_broadcast
+i
+1,
985 (broadcast_at_thread_exit
.used
-i
-1)*sizeof(broadcast_at_thread_exit
.to_broadcast
[0]));
986 broadcast_at_thread_exit
.used
--;
989 LeaveCriticalSection(&broadcast_at_thread_exit_cs
);
994 #if _MSVCP_VER == 100
996 const vtable_ptr
*vtable
;
1000 error_category base
;
1003 static custom_category iostream_category
;
1005 DEFINE_RTTI_DATA0(error_category
, 0, ".?AVerror_category@std@@")
1006 DEFINE_RTTI_DATA1(iostream_category
, 0, &error_category_rtti_base_descriptor
, ".?AV_Iostream_error_category@std@@")
1008 extern const vtable_ptr MSVCP_iostream_category_vtable
;
1010 static void iostream_category_ctor(custom_category
*this)
1012 this->base
.vtable
= &MSVCP_iostream_category_vtable
;
1013 this->type
= "iostream";
1016 DEFINE_THISCALL_WRAPPER(custom_category_vector_dtor
, 8)
1017 custom_category
* __thiscall
custom_category_vector_dtor(custom_category
*this, unsigned int flags
)
1019 TRACE("(%p %x)\n", this, flags
);
1021 /* we have an array, with the number of elements stored before the first object */
1022 INT_PTR i
, *ptr
= (INT_PTR
*)this-1;
1024 for(i
=*ptr
-1; i
>=0; i
--)
1025 MSVCRT_operator_delete(ptr
);
1028 MSVCRT_operator_delete(this);
1034 DEFINE_THISCALL_WRAPPER(custom_category_name
, 4)
1035 const char* __thiscall
custom_category_name(const custom_category
*this)
1040 DEFINE_THISCALL_WRAPPER(custom_category_message
, 12)
1041 basic_string_char
* __thiscall
custom_category_message(const custom_category
*this,
1042 basic_string_char
*ret
, int err
)
1044 return MSVCP_basic_string_char_ctor_cstr(ret
, strerror(err
));
1047 DEFINE_THISCALL_WRAPPER(custom_category_default_error_condition
, 12)
1048 /*error_condition*/void* __thiscall
custom_category_default_error_condition(
1049 custom_category
*this, /*error_condition*/void *ret
, int code
)
1051 FIXME("(%p %p %x) stub\n", this, ret
, code
);
1055 DEFINE_THISCALL_WRAPPER(custom_category_equivalent
, 12)
1056 MSVCP_bool __thiscall
custom_category_equivalent(const custom_category
*this,
1057 int code
, const /*error_condition*/void *condition
)
1059 FIXME("(%p %x %p) stub\n", this, code
, condition
);
1063 DEFINE_THISCALL_WRAPPER(custom_category_equivalent_code
, 12)
1064 MSVCP_bool __thiscall
custom_category_equivalent_code(custom_category
*this,
1065 const /*error_code*/void *code
, int condition
)
1067 FIXME("(%p %p %x) stub\n", this, code
, condition
);
1071 DEFINE_THISCALL_WRAPPER(iostream_category_message
, 12)
1072 basic_string_char
* __thiscall
iostream_category_message(const custom_category
*this,
1073 basic_string_char
*ret
, int err
)
1075 if(err
== 1) return MSVCP_basic_string_char_ctor_cstr(ret
, "iostream error");
1076 return MSVCP_basic_string_char_ctor_cstr(ret
, strerror(err
));
1079 /* ?iostream_category@std@@YAABVerror_category@1@XZ */
1080 /* ?iostream_category@std@@YAAEBVerror_category@1@XZ */
1081 const error_category
* __cdecl
std_iostream_category(void)
1084 return &iostream_category
.base
;
1087 static custom_category system_category
;
1088 DEFINE_RTTI_DATA1(system_category
, 0, &error_category_rtti_base_descriptor
, ".?AV_System_error_category@std@@")
1090 extern const vtable_ptr MSVCP_system_category_vtable
;
1092 static void system_category_ctor(custom_category
*this)
1094 this->base
.vtable
= &MSVCP_system_category_vtable
;
1095 this->type
= "system";
1098 /* ?system_category@std@@YAABVerror_category@1@XZ */
1099 /* ?system_category@std@@YAAEBVerror_category@1@XZ */
1100 const error_category
* __cdecl
std_system_category(void)
1103 return &system_category
.base
;
1106 static custom_category generic_category
;
1107 DEFINE_RTTI_DATA1(generic_category
, 0, &error_category_rtti_base_descriptor
, ".?AV_Generic_error_category@std@@")
1109 extern const vtable_ptr MSVCP_generic_category_vtable
;
1111 static void generic_category_ctor(custom_category
*this)
1113 this->base
.vtable
= &MSVCP_generic_category_vtable
;
1114 this->type
= "generic";
1117 /* ?generic_category@std@@YAABVerror_category@1@XZ */
1118 /* ?generic_category@std@@YAAEBVerror_category@1@XZ */
1119 const error_category
* __cdecl
std_generic_category(void)
1122 return &generic_category
.base
;
1126 #if _MSVCP_VER >= 110
1127 static CRITICAL_SECTION call_once_cs
;
1128 static CRITICAL_SECTION_DEBUG call_once_cs_debug
=
1130 0, 0, &call_once_cs
,
1131 { &call_once_cs_debug
.ProcessLocksList
, &call_once_cs_debug
.ProcessLocksList
},
1132 0, 0, { (DWORD_PTR
)(__FILE__
": call_once_cs") }
1134 static CRITICAL_SECTION call_once_cs
= { &call_once_cs_debug
, -1, 0, 0, 0, 0 };
1136 void __cdecl
_Call_onceEx(int *once
, void (__cdecl
*func
)(void*), void *argv
)
1138 TRACE("%p %p %p\n", once
, func
, argv
);
1140 EnterCriticalSection(&call_once_cs
);
1142 /* FIXME: handle exceptions */
1146 LeaveCriticalSection(&call_once_cs
);
1149 static void __cdecl
call_once_func_wrapper(void *func
)
1151 ((void (__cdecl
*)(void))func
)();
1154 void __cdecl
_Call_once(int *once
, void (__cdecl
*func
)(void))
1156 TRACE("%p %p\n", once
, func
);
1157 _Call_onceEx(once
, call_once_func_wrapper
, func
);
1160 void __cdecl
_Do_call(void *this)
1162 CALL_VTBL_FUNC(this, 0, void, (void*), (this));
1166 #if _MSVCP_VER >= 110
1173 typedef int (__cdecl
*_Thrd_start_t
)(void*);
1175 #define _THRD_ERROR 4
1177 int __cdecl
_Thrd_equal(_Thrd_t a
, _Thrd_t b
)
1179 TRACE("(%p %u %p %u)\n", a
.hnd
, a
.id
, b
.hnd
, b
.id
);
1180 return a
.id
== b
.id
;
1183 int __cdecl
_Thrd_lt(_Thrd_t a
, _Thrd_t b
)
1185 TRACE("(%p %u %p %u)\n", a
.hnd
, a
.id
, b
.hnd
, b
.id
);
1189 void __cdecl
_Thrd_sleep(const xtime
*t
)
1192 Sleep(_Xtime_diff_to_millis(t
));
1195 void __cdecl
_Thrd_yield(void)
1201 static _Thrd_t
thread_current(void)
1205 if(DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
1206 GetCurrentProcess(), &ret
.hnd
, 0, FALSE
, DUPLICATE_SAME_ACCESS
)) {
1207 CloseHandle(ret
.hnd
);
1211 ret
.id
= GetCurrentThreadId();
1213 TRACE("(%p %u)\n", ret
.hnd
, ret
.id
);
1218 _Thrd_t __cdecl
_Thrd_current(void)
1220 return thread_current();
1223 ULONGLONG __cdecl
_Thrd_current(void)
1230 C_ASSERT(sizeof(_Thrd_t
) <= sizeof(ULONGLONG
));
1232 ret
.thr
= thread_current();
1237 int __cdecl
_Thrd_join(_Thrd_t thr
, int *code
)
1239 TRACE("(%p %u %p)\n", thr
.hnd
, thr
.id
, code
);
1240 if (WaitForSingleObject(thr
.hnd
, INFINITE
))
1244 GetExitCodeThread(thr
.hnd
, (DWORD
*)code
);
1246 CloseHandle(thr
.hnd
);
1250 int __cdecl
_Thrd_start(_Thrd_t
*thr
, LPTHREAD_START_ROUTINE proc
, void *arg
)
1252 TRACE("(%p %p %p)\n", thr
, proc
, arg
);
1253 thr
->hnd
= CreateThread(NULL
, 0, proc
, arg
, 0, &thr
->id
);
1254 return thr
->hnd
? 0 : _THRD_ERROR
;
1263 static DWORD WINAPI
thread_proc_wrapper(void *arg
)
1265 thread_proc_arg wrapped_arg
= *((thread_proc_arg
*)arg
);
1267 return wrapped_arg
.proc(wrapped_arg
.arg
);
1270 int __cdecl
_Thrd_create(_Thrd_t
*thr
, _Thrd_start_t proc
, void *arg
)
1272 thread_proc_arg
*wrapped_arg
;
1275 TRACE("(%p %p %p)\n", thr
, proc
, arg
);
1277 wrapped_arg
= malloc(sizeof(*wrapped_arg
));
1279 return _THRD_ERROR
; /* TODO: probably different error should be returned here */
1281 wrapped_arg
->proc
= proc
;
1282 wrapped_arg
->arg
= arg
;
1283 ret
= _Thrd_start(thr
, thread_proc_wrapper
, wrapped_arg
);
1284 if(ret
) free(wrapped_arg
);
1288 int __cdecl
_Thrd_detach(_Thrd_t thr
)
1290 return CloseHandle(thr
.hnd
) ? 0 : _THRD_ERROR
;
1295 const vtable_ptr
*vtable
;
1298 MSVCP_bool launched
;
1301 DEFINE_RTTI_DATA0(_Pad
, 0, ".?AV_Pad@std@@")
1303 /* ??_7_Pad@std@@6B@ */
1304 extern const vtable_ptr MSVCP__Pad_vtable
;
1306 unsigned int __cdecl
_Thrd_hardware_concurrency(void)
1308 static unsigned int val
= -1;
1316 val
= si
.dwNumberOfProcessors
;
1322 unsigned int __cdecl
_Thrd_id(void)
1325 return GetCurrentThreadId();
1328 /* ??0_Pad@std@@QAE@XZ */
1329 /* ??0_Pad@std@@QEAA@XZ */
1330 DEFINE_THISCALL_WRAPPER(_Pad_ctor
, 4)
1331 _Pad
* __thiscall
_Pad_ctor(_Pad
*this)
1333 TRACE("(%p)\n", this);
1335 this->vtable
= &MSVCP__Pad_vtable
;
1336 _Cnd_init(&this->cnd
);
1337 _Mtx_init(&this->mtx
, 0);
1338 this->launched
= FALSE
;
1339 _Mtx_lock(MTX_T_TO_ARG(this->mtx
));
1343 /* ??4_Pad@std@@QAEAAV01@ABV01@@Z */
1344 /* ??4_Pad@std@@QEAAAEAV01@AEBV01@@Z */
1345 DEFINE_THISCALL_WRAPPER(_Pad_op_assign
, 8)
1346 _Pad
* __thiscall
_Pad_op_assign(_Pad
*this, const _Pad
*copy
)
1348 TRACE("(%p %p)\n", this, copy
);
1350 this->cnd
= copy
->cnd
;
1351 this->mtx
= copy
->mtx
;
1352 this->launched
= copy
->launched
;
1356 /* ??0_Pad@std@@QAE@ABV01@@Z */
1357 /* ??0_Pad@std@@QEAA@AEBV01@@Z */
1358 DEFINE_THISCALL_WRAPPER(_Pad_copy_ctor
, 8)
1359 _Pad
* __thiscall
_Pad_copy_ctor(_Pad
*this, const _Pad
*copy
)
1361 TRACE("(%p %p)\n", this, copy
);
1363 this->vtable
= &MSVCP__Pad_vtable
;
1364 return _Pad_op_assign(this, copy
);
1367 /* ??1_Pad@std@@QAE@XZ */
1368 /* ??1_Pad@std@@QEAA@XZ */
1369 DEFINE_THISCALL_WRAPPER(_Pad_dtor
, 4)
1370 void __thiscall
_Pad_dtor(_Pad
*this)
1372 TRACE("(%p)\n", this);
1374 _Mtx_unlock(MTX_T_TO_ARG(this->mtx
));
1375 _Mtx_destroy(MTX_T_TO_ARG(this->mtx
));
1376 _Cnd_destroy(CND_T_TO_ARG(this->cnd
));
1379 DEFINE_THISCALL_WRAPPER(_Pad__Go
, 4)
1380 #define call__Pad__Go(this) CALL_VTBL_FUNC(this, 0, unsigned int, (_Pad*), (this))
1381 unsigned int __thiscall
_Pad__Go(_Pad
*this)
1383 ERR("(%p) should not be called\n", this);
1387 static DWORD WINAPI
launch_thread_proc(void *arg
)
1390 return call__Pad__Go(this);
1393 /* ?_Launch@_Pad@std@@QAEXPAU_Thrd_imp_t@@@Z */
1394 /* ?_Launch@_Pad@std@@QEAAXPEAU_Thrd_imp_t@@@Z */
1395 DEFINE_THISCALL_WRAPPER(_Pad__Launch
, 8)
1396 void __thiscall
_Pad__Launch(_Pad
*this, _Thrd_t
*thr
)
1398 TRACE("(%p %p)\n", this, thr
);
1400 _Thrd_start(thr
, launch_thread_proc
, this);
1401 _Cnd_wait(CND_T_TO_ARG(this->cnd
), MTX_T_TO_ARG(this->mtx
));
1404 /* ?_Release@_Pad@std@@QAEXXZ */
1405 /* ?_Release@_Pad@std@@QEAAXXZ */
1406 DEFINE_THISCALL_WRAPPER(_Pad__Release
, 4)
1407 void __thiscall
_Pad__Release(_Pad
*this)
1409 TRACE("(%p)\n", this);
1411 _Mtx_lock(MTX_T_TO_ARG(this->mtx
));
1412 this->launched
= TRUE
;
1413 _Cnd_signal(CND_T_TO_ARG(this->cnd
));
1414 _Mtx_unlock(MTX_T_TO_ARG(this->mtx
));
1418 #if _MSVCP_VER >= 100
1419 typedef struct _Page
1421 struct _Page
*_Next
;
1431 MSVCP_size_t head_pos
;
1432 MSVCP_size_t tail_pos
;
1438 MSVCP_size_t tail_pos
;
1439 MSVCP_size_t head_pos
;
1440 threadsafe_queue queues
[QUEUES_NO
];
1445 const vtable_ptr
*vtable
;
1446 queue_data
*data
; /* queue_data structure is not binary compatible */
1447 MSVCP_size_t alloc_count
;
1448 MSVCP_size_t item_size
;
1449 } _Concurrent_queue_base_v4
;
1451 extern const vtable_ptr MSVCP__Concurrent_queue_base_v4_vtable
;
1452 #if _MSVCP_VER == 100
1453 #define call__Concurrent_queue_base_v4__Move_item call__Concurrent_queue_base_v4__Copy_item
1454 #define call__Concurrent_queue_base_v4__Copy_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1455 0, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,const void*), (this,dst,idx,src))
1456 #define call__Concurrent_queue_base_v4__Assign_and_destroy_item(this,dst,src,idx) CALL_VTBL_FUNC(this, \
1457 4, void, (_Concurrent_queue_base_v4*,void*,_Page*,MSVCP_size_t), (this,dst,src,idx))
1458 #define call__Concurrent_queue_base_v4__Allocate_page(this) CALL_VTBL_FUNC(this, \
1459 12, _Page*, (_Concurrent_queue_base_v4*), (this))
1460 #define call__Concurrent_queue_base_v4__Deallocate_page(this, page) CALL_VTBL_FUNC(this, \
1461 16, void, (_Concurrent_queue_base_v4*,_Page*), (this,page))
1463 #define call__Concurrent_queue_base_v4__Move_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1464 0, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,void*), (this,dst,idx,src))
1465 #define call__Concurrent_queue_base_v4__Copy_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1466 4, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,const void*), (this,dst,idx,src))
1467 #define call__Concurrent_queue_base_v4__Assign_and_destroy_item(this,dst,src,idx) CALL_VTBL_FUNC(this, \
1468 8, void, (_Concurrent_queue_base_v4*,void*,_Page*,MSVCP_size_t), (this,dst,src,idx))
1469 #define call__Concurrent_queue_base_v4__Allocate_page(this) CALL_VTBL_FUNC(this, \
1470 16, _Page*, (_Concurrent_queue_base_v4*), (this))
1471 #define call__Concurrent_queue_base_v4__Deallocate_page(this, page) CALL_VTBL_FUNC(this, \
1472 20, void, (_Concurrent_queue_base_v4*,_Page*), (this,page))
1475 /* ?_Internal_throw_exception@_Concurrent_queue_base_v4@details@Concurrency@@IBEXXZ */
1476 /* ?_Internal_throw_exception@_Concurrent_queue_base_v4@details@Concurrency@@IEBAXXZ */
1477 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_throw_exception
, 4)
1478 void __thiscall
_Concurrent_queue_base_v4__Internal_throw_exception(
1479 const _Concurrent_queue_base_v4
*this)
1481 TRACE("(%p)\n", this);
1482 throw_exception(EXCEPTION_BAD_ALLOC
, NULL
);
1485 /* ??0_Concurrent_queue_base_v4@details@Concurrency@@IAE@I@Z */
1486 /* ??0_Concurrent_queue_base_v4@details@Concurrency@@IEAA@_K@Z */
1487 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_ctor
, 8)
1488 _Concurrent_queue_base_v4
* __thiscall
_Concurrent_queue_base_v4_ctor(
1489 _Concurrent_queue_base_v4
*this, MSVCP_size_t size
)
1491 TRACE("(%p %ld)\n", this, size
);
1493 this->data
= MSVCRT_operator_new(sizeof(*this->data
));
1494 memset(this->data
, 0, sizeof(*this->data
));
1496 this->vtable
= &MSVCP__Concurrent_queue_base_v4_vtable
;
1497 this->item_size
= size
;
1499 /* alloc_count needs to be power of 2 */
1505 size
<= 128 ? 2 : 1;
1509 /* ??1_Concurrent_queue_base_v4@details@Concurrency@@MAE@XZ */
1510 /* ??1_Concurrent_queue_base_v4@details@Concurrency@@MEAA@XZ */
1511 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_dtor
, 4)
1512 void __thiscall
_Concurrent_queue_base_v4_dtor(_Concurrent_queue_base_v4
*this)
1514 TRACE("(%p)\n", this);
1515 MSVCRT_operator_delete(this->data
);
1518 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_vector_dtor
, 8)
1519 _Concurrent_queue_base_v4
* __thiscall
_Concurrent_queue_base_v4_vector_dtor(
1520 _Concurrent_queue_base_v4
*this, unsigned int flags
)
1522 TRACE("(%p %x)\n", this, flags
);
1524 /* we have an array, with the number of elements stored before the first object */
1525 INT_PTR i
, *ptr
= (INT_PTR
*)this-1;
1527 for(i
=*ptr
-1; i
>=0; i
--)
1528 _Concurrent_queue_base_v4_dtor(this+i
);
1529 MSVCRT_operator_delete(ptr
);
1532 _Concurrent_queue_base_v4_dtor(this);
1533 MSVCRT_operator_delete(this);
1539 /* ?_Internal_finish_clear@_Concurrent_queue_base_v4@details@Concurrency@@IAEXXZ */
1540 /* ?_Internal_finish_clear@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXXZ */
1541 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_finish_clear
, 4)
1542 void __thiscall
_Concurrent_queue_base_v4__Internal_finish_clear(
1543 _Concurrent_queue_base_v4
*this)
1547 TRACE("(%p)\n", this);
1549 for(i
=0; i
<QUEUES_NO
; i
++)
1551 if(this->data
->queues
[i
].tail
)
1552 call__Concurrent_queue_base_v4__Deallocate_page(this, this->data
->queues
[i
].tail
);
1556 /* ?_Internal_empty@_Concurrent_queue_base_v4@details@Concurrency@@IBE_NXZ */
1557 /* ?_Internal_empty@_Concurrent_queue_base_v4@details@Concurrency@@IEBA_NXZ */
1558 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_empty
, 4)
1559 MSVCP_bool __thiscall
_Concurrent_queue_base_v4__Internal_empty(
1560 const _Concurrent_queue_base_v4
*this)
1562 TRACE("(%p)\n", this);
1563 return this->data
->head_pos
== this->data
->tail_pos
;
1566 /* ?_Internal_size@_Concurrent_queue_base_v4@details@Concurrency@@IBEIXZ */
1567 /* ?_Internal_size@_Concurrent_queue_base_v4@details@Concurrency@@IEBA_KXZ */
1568 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_size
, 4)
1569 MSVCP_size_t __thiscall
_Concurrent_queue_base_v4__Internal_size(
1570 const _Concurrent_queue_base_v4
*this)
1572 TRACE("(%p)\n", this);
1573 return this->data
->tail_pos
- this->data
->head_pos
;
1576 static void spin_wait(int *counter
)
1578 static int spin_limit
= -1;
1580 if(spin_limit
== -1)
1584 spin_limit
= si
.dwNumberOfProcessors
>1 ? 4000 : 0;
1587 if(*counter
>= spin_limit
)
1599 static MSVCP_size_t
InterlockedIncrementSizeT(MSVCP_size_t
volatile *dest
)
1606 } while(InterlockedCompareExchange64((LONGLONG
*)dest
, v
+1, v
) != v
);
1611 #define InterlockedIncrementSizeT(dest) InterlockedIncrement((LONG*)dest)
1614 static void CALLBACK
queue_push_finally(BOOL normal
, void *ctx
)
1616 threadsafe_queue
*queue
= ctx
;
1617 InterlockedIncrementSizeT(&queue
->tail_pos
);
1620 static void threadsafe_queue_push(threadsafe_queue
*queue
, MSVCP_size_t id
,
1621 void *e
, _Concurrent_queue_base_v4
*parent
, BOOL copy
)
1623 MSVCP_size_t page_id
= id
& ~(parent
->alloc_count
-1);
1628 while(queue
->tail_pos
!= id
)
1633 /* TODO: Add exception handling */
1634 p
= call__Concurrent_queue_base_v4__Allocate_page(parent
);
1639 while(InterlockedCompareExchange(&queue
->lock
, 1, 0))
1642 queue
->tail
->_Next
= p
;
1656 call__Concurrent_queue_base_v4__Copy_item(parent
, p
, id
-page_id
, e
);
1658 call__Concurrent_queue_base_v4__Move_item(parent
, p
, id
-page_id
, e
);
1659 p
->_Mask
|= 1 << (id
- page_id
);
1661 __FINALLY_CTX(queue_push_finally
, queue
);
1664 static BOOL
threadsafe_queue_pop(threadsafe_queue
*queue
, MSVCP_size_t id
,
1665 void *e
, _Concurrent_queue_base_v4
*parent
)
1667 MSVCP_size_t page_id
= id
& ~(parent
->alloc_count
-1);
1673 while(queue
->tail_pos
<= id
)
1677 while(queue
->head_pos
!= id
)
1681 if(p
->_Mask
& (1 << (id
-page_id
)))
1683 /* TODO: Add exception handling */
1684 call__Concurrent_queue_base_v4__Assign_and_destroy_item(parent
, e
, p
, id
-page_id
);
1688 if(id
== page_id
+parent
->alloc_count
-1)
1691 while(InterlockedCompareExchange(&queue
->lock
, 1, 0))
1693 queue
->head
= p
->_Next
;
1698 /* TODO: Add exception handling */
1699 call__Concurrent_queue_base_v4__Deallocate_page(parent
, p
);
1702 InterlockedIncrementSizeT(&queue
->head_pos
);
1706 /* ?_Internal_push@_Concurrent_queue_base_v4@details@Concurrency@@IAEXPBX@Z */
1707 /* ?_Internal_push@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXPEBX@Z */
1708 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_push
, 8)
1709 void __thiscall
_Concurrent_queue_base_v4__Internal_push(
1710 _Concurrent_queue_base_v4
*this, void *e
)
1714 TRACE("(%p %p)\n", this, e
);
1716 id
= InterlockedIncrementSizeT(&this->data
->tail_pos
)-1;
1717 threadsafe_queue_push(this->data
->queues
+ id
% QUEUES_NO
,
1718 id
/ QUEUES_NO
, e
, this, TRUE
);
1721 /* ?_Internal_move_push@_Concurrent_queue_base_v4@details@Concurrency@@IAEXPAX@Z */
1722 /* ?_Internal_move_push@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXPEAX@Z */
1723 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_move_push
, 8)
1724 void __thiscall
_Concurrent_queue_base_v4__Internal_move_push(
1725 _Concurrent_queue_base_v4
*this, void *e
)
1729 TRACE("(%p %p)\n", this, e
);
1731 id
= InterlockedIncrementSizeT(&this->data
->tail_pos
)-1;
1732 threadsafe_queue_push(this->data
->queues
+ id
% QUEUES_NO
,
1733 id
/ QUEUES_NO
, e
, this, FALSE
);
1736 /* ?_Internal_pop_if_present@_Concurrent_queue_base_v4@details@Concurrency@@IAE_NPAX@Z */
1737 /* ?_Internal_pop_if_present@_Concurrent_queue_base_v4@details@Concurrency@@IEAA_NPEAX@Z */
1738 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_pop_if_present
, 8)
1739 MSVCP_bool __thiscall
_Concurrent_queue_base_v4__Internal_pop_if_present(
1740 _Concurrent_queue_base_v4
*this, void *e
)
1744 TRACE("(%p %p)\n", this, e
);
1750 id
= this->data
->head_pos
;
1751 if(id
== this->data
->tail_pos
) return FALSE
;
1752 } while(InterlockedCompareExchangePointer((void**)&this->data
->head_pos
,
1753 (void*)(id
+1), (void*)id
) != (void*)id
);
1754 } while(!threadsafe_queue_pop(this->data
->queues
+ id
% QUEUES_NO
,
1755 id
/ QUEUES_NO
, e
, this));
1759 /* ?_Internal_swap@_Concurrent_queue_base_v4@details@Concurrency@@IAEXAAV123@@Z */
1760 /* ?_Internal_swap@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXAEAV123@@Z */
1761 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_swap
, 8)
1762 void __thiscall
_Concurrent_queue_base_v4__Internal_swap(
1763 _Concurrent_queue_base_v4
*this, _Concurrent_queue_base_v4
*r
)
1765 FIXME("(%p %p) stub\n", this, r
);
1768 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_dummy
, 4)
1769 void __thiscall
_Concurrent_queue_base_v4_dummy(_Concurrent_queue_base_v4
*this)
1771 ERR("unexpected call\n");
1774 DEFINE_RTTI_DATA0(_Concurrent_queue_base_v4
, 0, ".?AV_Concurrent_queue_base_v4@details@Concurrency@@")
1776 static int _Runtime_object_id
;
1780 const vtable_ptr
*vtable
;
1784 extern const vtable_ptr MSVCP__Runtime_object_vtable
;
1786 /* ??0_Runtime_object@details@Concurrency@@QAE@H@Z */
1787 /* ??0_Runtime_object@details@Concurrency@@QEAA@H@Z */
1788 DEFINE_THISCALL_WRAPPER(_Runtime_object_ctor_id
, 8)
1789 _Runtime_object
* __thiscall
_Runtime_object_ctor_id(_Runtime_object
*this, int id
)
1791 TRACE("(%p %d)\n", this, id
);
1792 this->vtable
= &MSVCP__Runtime_object_vtable
;
1797 /* ??0_Runtime_object@details@Concurrency@@QAE@XZ */
1798 /* ??0_Runtime_object@details@Concurrency@@QEAA@XZ */
1799 DEFINE_THISCALL_WRAPPER(_Runtime_object_ctor
, 4)
1800 _Runtime_object
* __thiscall
_Runtime_object_ctor(_Runtime_object
*this)
1802 TRACE("(%p)\n", this);
1803 this->vtable
= &MSVCP__Runtime_object_vtable
;
1804 this->id
= InterlockedExchangeAdd(&_Runtime_object_id
, 2);
1808 DEFINE_THISCALL_WRAPPER(_Runtime_object__GetId
, 4)
1809 int __thiscall
_Runtime_object__GetId(_Runtime_object
*this)
1811 TRACE("(%p)\n", this);
1815 DEFINE_RTTI_DATA0(_Runtime_object
, 0, ".?AV_Runtime_object@details@Concurrency@@")
1819 #if _MSVCP_VER >= 100
1820 typedef struct __Concurrent_vector_base_v4
1822 void* (__cdecl
*allocator
)(struct __Concurrent_vector_base_v4
*, MSVCP_size_t
);
1824 MSVCP_size_t first_block
;
1825 MSVCP_size_t early_size
;
1827 } _Concurrent_vector_base_v4
;
1829 #define STORAGE_SIZE ARRAY_SIZE(this->storage)
1830 #define SEGMENT_SIZE (sizeof(void*) * 8)
1832 typedef struct compact_block
1834 MSVCP_size_t first_block
;
1835 void *blocks
[SEGMENT_SIZE
];
1839 /* based on wined3d_log2i from wined3d.h */
1840 /* Return the integer base-2 logarithm of (x|1). Result is 0 for x == 0. */
1841 static inline unsigned int log2i(unsigned int x
)
1843 #ifdef HAVE___BUILTIN_CLZ
1844 return __builtin_clz(x
|1) ^ 0x1f;
1846 static const unsigned int l
[] =
1848 ~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
1849 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1850 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1851 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1852 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1853 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1854 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1855 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1856 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1857 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1858 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1859 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1860 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1861 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1862 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1863 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1868 return (i
= x
>> 16) ? (x
= i
>> 8) ? l
[x
] + 24 : l
[i
] + 16 : (i
= x
>> 8) ? l
[i
] + 8 : l
[x
];
1872 /* ?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KAII@Z */
1873 /* ?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KA_K_K@Z */
1874 MSVCP_size_t __cdecl
_vector_base_v4__Segment_index_of(MSVCP_size_t x
)
1878 TRACE("(%lu)\n", x
);
1880 if((sizeof(x
) == 8) && (half
= x
>> 32))
1881 return log2i(half
) + 32;
1886 /* ?_Internal_throw_exception@_Concurrent_vector_base_v4@details@Concurrency@@IBEXI@Z */
1887 /* ?_Internal_throw_exception@_Concurrent_vector_base_v4@details@Concurrency@@IEBAX_K@Z */
1888 DEFINE_THISCALL_WRAPPER(_vector_base_v4__Internal_throw_exception
, 8)
1889 void __thiscall
_vector_base_v4__Internal_throw_exception(void/*_vector_base_v4*/ *this, MSVCP_size_t idx
)
1891 static const struct {
1892 exception_type type
;
1895 { EXCEPTION_OUT_OF_RANGE
, "Index out of range" },
1896 { EXCEPTION_OUT_OF_RANGE
, "Index out of segments table range" },
1897 { EXCEPTION_RANGE_ERROR
, "Index is inside segment which failed to be allocated" },
1900 TRACE("(%p %lu)\n", this, idx
);
1902 if(idx
< ARRAY_SIZE(exceptions
))
1903 throw_exception(exceptions
[idx
].type
, exceptions
[idx
].msg
);
1907 #define InterlockedCompareExchangeSizeT(dest, exchange, cmp) InterlockedCompareExchangeSize((MSVCP_size_t *)dest, (MSVCP_size_t)exchange, (MSVCP_size_t)cmp)
1908 static MSVCP_size_t
InterlockedCompareExchangeSize(MSVCP_size_t
volatile *dest
, MSVCP_size_t exchange
, MSVCP_size_t cmp
)
1912 v
= InterlockedCompareExchange64((LONGLONG
*)dest
, exchange
, cmp
);
1917 #define InterlockedCompareExchangeSizeT(dest, exchange, cmp) InterlockedCompareExchange((LONG*)dest, (MSVCP_size_t)exchange, (MSVCP_size_t)cmp)
1920 #define SEGMENT_ALLOC_MARKER ((void*)1)
1922 static void concurrent_vector_alloc_segment(_Concurrent_vector_base_v4
*this,
1923 MSVCP_size_t seg
, MSVCP_size_t element_size
)
1927 while(!this->segment
[seg
] || this->segment
[seg
] == SEGMENT_ALLOC_MARKER
)
1930 while(this->segment
[seg
] == SEGMENT_ALLOC_MARKER
)
1932 if(!InterlockedCompareExchangeSizeT((this->segment
+ seg
),
1933 SEGMENT_ALLOC_MARKER
, 0))
1937 this->segment
[seg
] = this->allocator(this, element_size
* (1 << this->first_block
));
1938 else if(seg
< this->first_block
)
1939 this->segment
[seg
] = (BYTE
**)this->segment
[0]
1940 + element_size
* (1 << seg
);
1942 this->segment
[seg
] = this->allocator(this, element_size
* (1 << seg
));
1946 this->segment
[seg
] = NULL
;
1947 throw_exception(EXCEPTION_RERAISE
, NULL
);
1950 if(!this->segment
[seg
])
1951 _vector_base_v4__Internal_throw_exception(this, 2);
1955 /* ??1_Concurrent_vector_base_v4@details@Concurrency@@IAE@XZ */
1956 /* ??1_Concurrent_vector_base_v4@details@Concurrency@@IEAA@XZ */
1957 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4_dtor
, 4)
1958 void __thiscall
_Concurrent_vector_base_v4_dtor(
1959 _Concurrent_vector_base_v4
*this)
1961 TRACE("(%p)\n", this);
1963 if(this->segment
!= this->storage
)
1964 free(this->segment
);
1967 /* ?_Internal_capacity@_Concurrent_vector_base_v4@details@Concurrency@@IBEIXZ */
1968 /* ?_Internal_capacity@_Concurrent_vector_base_v4@details@Concurrency@@IEBA_KXZ */
1969 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_capacity
, 4)
1970 MSVCP_size_t __thiscall
_Concurrent_vector_base_v4__Internal_capacity(
1971 const _Concurrent_vector_base_v4
*this)
1973 MSVCP_size_t last_block
;
1976 TRACE("(%p)\n", this);
1978 last_block
= (this->segment
== this->storage
? STORAGE_SIZE
: SEGMENT_SIZE
);
1979 for(i
= 0; i
< last_block
; i
++)
1981 if(!this->segment
[i
])
1982 return !i
? 0 : 1 << i
;
1987 /* ?_Internal_reserve@_Concurrent_vector_base_v4@details@Concurrency@@IAEXIII@Z */
1988 /* ?_Internal_reserve@_Concurrent_vector_base_v4@details@Concurrency@@IEAAX_K00@Z */
1989 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_reserve
, 16)
1990 void __thiscall
_Concurrent_vector_base_v4__Internal_reserve(
1991 _Concurrent_vector_base_v4
*this, MSVCP_size_t size
,
1992 MSVCP_size_t element_size
, MSVCP_size_t max_size
)
1994 MSVCP_size_t block_idx
, capacity
;
1998 TRACE("(%p %ld %ld %ld)\n", this, size
, element_size
, max_size
);
2000 if(size
> max_size
) _vector_base_v4__Internal_throw_exception(this, 0);
2001 capacity
= _Concurrent_vector_base_v4__Internal_capacity(this);
2002 if(size
<= capacity
) return;
2003 block_idx
= _vector_base_v4__Segment_index_of(size
- 1);
2004 if(!this->first_block
)
2005 InterlockedCompareExchangeSizeT(&this->first_block
, block_idx
+ 1, 0);
2006 i
= _vector_base_v4__Segment_index_of(capacity
);
2007 if(this->storage
== this->segment
) {
2008 for(; i
<= block_idx
&& i
< STORAGE_SIZE
; i
++)
2009 concurrent_vector_alloc_segment(this, i
, element_size
);
2010 if(block_idx
>= STORAGE_SIZE
) {
2011 new_segment
= malloc(SEGMENT_SIZE
* sizeof(void*));
2012 if(new_segment
== NULL
) _vector_base_v4__Internal_throw_exception(this, 2);
2013 memset(new_segment
, 0, SEGMENT_SIZE
* sizeof(*new_segment
));
2014 memcpy(new_segment
, this->storage
, STORAGE_SIZE
* sizeof(*new_segment
));
2015 if(InterlockedCompareExchangePointer((void*)&this->segment
, new_segment
,
2016 this->storage
) != this->storage
)
2020 for(; i
<= block_idx
; i
++)
2021 concurrent_vector_alloc_segment(this, i
, element_size
);
2024 /* ?_Internal_clear@_Concurrent_vector_base_v4@details@Concurrency@@IAEIP6AXPAXI@Z@Z */
2025 /* ?_Internal_clear@_Concurrent_vector_base_v4@details@Concurrency@@IEAA_KP6AXPEAX_K@Z@Z */
2026 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_clear
, 8)
2027 MSVCP_size_t __thiscall
_Concurrent_vector_base_v4__Internal_clear(
2028 _Concurrent_vector_base_v4
*this, void (__cdecl
*clear
)(void*, MSVCP_size_t
))
2030 MSVCP_size_t seg_no
, elems
;
2033 TRACE("(%p %p)\n", this, clear
);
2035 seg_no
= this->early_size
? _vector_base_v4__Segment_index_of(this->early_size
) + 1 : 0;
2036 for(i
= seg_no
- 1; i
>= 0; i
--) {
2037 elems
= this->early_size
- (1 << i
& ~1);
2038 clear(this->segment
[i
], elems
);
2039 this->early_size
-= elems
;
2041 while(seg_no
< (this->segment
== this->storage
? STORAGE_SIZE
: SEGMENT_SIZE
)) {
2042 if(!this->segment
[seg_no
]) break;
2048 /* ?_Internal_compact@_Concurrent_vector_base_v4@details@Concurrency@@IAEPAXIPAXP6AX0I@ZP6AX0PBXI@Z@Z */
2049 /* ?_Internal_compact@_Concurrent_vector_base_v4@details@Concurrency@@IEAAPEAX_KPEAXP6AX10@ZP6AX1PEBX0@Z@Z */
2050 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_compact
, 20)
2051 void * __thiscall
_Concurrent_vector_base_v4__Internal_compact(
2052 _Concurrent_vector_base_v4
*this, MSVCP_size_t element_size
, void *v
,
2053 void (__cdecl
*clear
)(void*, MSVCP_size_t
),
2054 void (__cdecl
*copy
)(void*, const void*, MSVCP_size_t
))
2057 MSVCP_size_t size
, alloc_size
, seg_no
, alloc_seg
, copy_element
, clear_element
;
2060 TRACE("(%p %ld %p %p %p)\n", this, element_size
, v
, clear
, copy
);
2062 size
= this->early_size
;
2063 alloc_size
= _Concurrent_vector_base_v4__Internal_capacity(this);
2064 if(alloc_size
== 0) return NULL
;
2065 alloc_seg
= _vector_base_v4__Segment_index_of(alloc_size
- 1);
2067 this->first_block
= 0;
2069 b
->first_block
= alloc_seg
+ 1;
2070 memset(b
->blocks
, 0, sizeof(b
->blocks
));
2071 memcpy(b
->blocks
, this->segment
,
2072 (alloc_seg
+ 1) * sizeof(this->segment
[0]));
2073 memset(this->segment
, 0, sizeof(this->segment
[0]) * (alloc_seg
+ 1));
2076 seg_no
= _vector_base_v4__Segment_index_of(size
- 1);
2077 if(this->first_block
== (seg_no
+ 1) && seg_no
== alloc_seg
) return NULL
;
2079 b
->first_block
= this->first_block
;
2080 memset(b
->blocks
, 0, sizeof(b
->blocks
));
2081 memcpy(b
->blocks
, this->segment
,
2082 (alloc_seg
+ 1) * sizeof(this->segment
[0]));
2083 if(this->first_block
== (seg_no
+ 1) && seg_no
!= alloc_seg
) {
2084 memset(b
->blocks
, 0, sizeof(b
->blocks
[0]) * (seg_no
+ 1));
2085 memset(&this->segment
[seg_no
+ 1], 0, sizeof(this->segment
[0]) * (alloc_seg
- seg_no
));
2088 memset(this->segment
, 0,
2089 (alloc_seg
+ 1) * sizeof(this->segment
[0]));
2090 this->first_block
= 0;
2091 _Concurrent_vector_base_v4__Internal_reserve(this, size
, element_size
,
2092 MSVCP_SIZE_T_MAX
/ element_size
);
2093 for(i
= 0; i
< seg_no
; i
++)
2094 copy(this->segment
[i
], b
->blocks
[i
], i
? 1 << i
: 2);
2095 copy_element
= size
- ((1 << seg_no
) & ~1);
2096 if(copy_element
> 0)
2097 copy(this->segment
[seg_no
], b
->blocks
[seg_no
], copy_element
);
2098 for(i
= 0; i
< seg_no
; i
++)
2099 clear(b
->blocks
[i
], i
? 1 << i
: 2);
2100 clear_element
= size
- ((1 << seg_no
) & ~1);
2101 if(clear_element
> 0)
2102 clear(b
->blocks
[seg_no
], clear_element
);
2106 /* ?_Internal_copy@_Concurrent_vector_base_v4@details@Concurrency@@IAEXABV123@IP6AXPAXPBXI@Z@Z */
2107 /* ?_Internal_copy@_Concurrent_vector_base_v4@details@Concurrency@@IEAAXAEBV123@_KP6AXPEAXPEBX1@Z@Z */
2108 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_copy
, 16)
2109 void __thiscall
_Concurrent_vector_base_v4__Internal_copy(
2110 _Concurrent_vector_base_v4
*this, const _Concurrent_vector_base_v4
*v
,
2111 MSVCP_size_t element_size
, void (__cdecl
*copy
)(void*, const void*, MSVCP_size_t
))
2113 MSVCP_size_t seg_no
, v_size
;
2116 TRACE("(%p %p %ld %p)\n", this, v
, element_size
, copy
);
2118 v_size
= v
->early_size
;
2120 this->early_size
= 0;
2123 _Concurrent_vector_base_v4__Internal_reserve(this, v_size
,
2124 element_size
, MSVCP_SIZE_T_MAX
/ element_size
);
2125 seg_no
= _vector_base_v4__Segment_index_of(v_size
- 1);
2126 for(i
= 0; i
< seg_no
; i
++)
2127 copy(this->segment
[i
], v
->segment
[i
], i
? 1 << i
: 2);
2128 copy(this->segment
[i
], v
->segment
[i
], v_size
- (1 << i
& ~1));
2129 this->early_size
= v_size
;
2132 /* ?_Internal_assign@_Concurrent_vector_base_v4@details@Concurrency@@IAEXABV123@IP6AXPAXI@ZP6AX1PBXI@Z4@Z */
2133 /* ?_Internal_assign@_Concurrent_vector_base_v4@details@Concurrency@@IEAAXAEBV123@_KP6AXPEAX1@ZP6AX2PEBX1@Z5@Z */
2134 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_assign
, 24)
2135 void __thiscall
_Concurrent_vector_base_v4__Internal_assign(
2136 _Concurrent_vector_base_v4
*this, const _Concurrent_vector_base_v4
*v
,
2137 MSVCP_size_t element_size
, void (__cdecl
*clear
)(void*, MSVCP_size_t
),
2138 void (__cdecl
*assign
)(void*, const void*, MSVCP_size_t
),
2139 void (__cdecl
*copy
)(void*, const void*, MSVCP_size_t
))
2141 MSVCP_size_t v_size
, seg_no
, v_seg_no
, remain_element
;
2144 TRACE("(%p %p %ld %p %p %p)\n", this, v
, element_size
, clear
, assign
, copy
);
2146 v_size
= v
->early_size
;
2148 _Concurrent_vector_base_v4__Internal_clear(this, clear
);
2151 if(!this->early_size
) {
2152 _Concurrent_vector_base_v4__Internal_copy(this, v
, element_size
, copy
);
2155 seg_no
= _vector_base_v4__Segment_index_of(this->early_size
- 1);
2156 v_seg_no
= _vector_base_v4__Segment_index_of(v_size
- 1);
2158 for(i
= 0; i
< min(seg_no
, v_seg_no
); i
++)
2159 assign(this->segment
[i
], v
->segment
[i
], i
? 1 << i
: 2);
2160 remain_element
= min(this->early_size
, v_size
) - (1 << i
& ~1);
2161 if(remain_element
!= 0)
2162 assign(this->segment
[i
], v
->segment
[i
], remain_element
);
2164 if(this->early_size
> v_size
)
2166 if((i
? 1 << i
: 2) - remain_element
> 0)
2167 clear((BYTE
**)this->segment
[i
] + element_size
* remain_element
,
2168 (i
? 1 << i
: 2) - remain_element
);
2171 for(i
++; i
< seg_no
; i
++)
2172 clear(this->segment
[i
], 1 << i
);
2173 clear(this->segment
[i
], this->early_size
- (1 << i
));
2176 else if(this->early_size
< v_size
)
2178 if((i
? 1 << i
: 2) - remain_element
> 0)
2179 copy((BYTE
**)this->segment
[i
] + element_size
* remain_element
,
2180 (BYTE
**)v
->segment
[i
] + element_size
* remain_element
,
2181 (i
? 1 << i
: 2) - remain_element
);
2184 _Concurrent_vector_base_v4__Internal_reserve(this, v_size
,
2185 element_size
, MSVCP_SIZE_T_MAX
/ element_size
);
2186 for(i
++; i
< v_seg_no
; i
++)
2187 copy(this->segment
[i
], v
->segment
[i
], 1 << i
);
2188 copy(this->segment
[i
], v
->segment
[i
], v
->early_size
- (1 << i
));
2191 this->early_size
= v_size
;
2194 /* ?_Internal_grow_by@_Concurrent_vector_base_v4@details@Concurrency@@IAEIIIP6AXPAXPBXI@Z1@Z */
2195 /* ?_Internal_grow_by@_Concurrent_vector_base_v4@details@Concurrency@@IEAA_K_K0P6AXPEAXPEBX0@Z2@Z */
2196 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_grow_by
, 20)
2197 MSVCP_size_t __thiscall
_Concurrent_vector_base_v4__Internal_grow_by(
2198 _Concurrent_vector_base_v4
*this, MSVCP_size_t count
, MSVCP_size_t element_size
,
2199 void (__cdecl
*copy
)(void*, const void*, MSVCP_size_t
), const void *v
)
2201 MSVCP_size_t size
, seg_no
, last_seg_no
, remain_size
;
2203 TRACE("(%p %ld %ld %p %p)\n", this, count
, element_size
, copy
, v
);
2205 if(count
== 0) return this->early_size
;
2207 size
= this->early_size
;
2208 _Concurrent_vector_base_v4__Internal_reserve(this, size
+ count
, element_size
,
2209 MSVCP_SIZE_T_MAX
/ element_size
);
2210 } while(InterlockedCompareExchangeSizeT(&this->early_size
, size
+ count
, size
) != size
);
2212 seg_no
= size
? _vector_base_v4__Segment_index_of(size
- 1) : 0;
2213 last_seg_no
= _vector_base_v4__Segment_index_of(size
+ count
- 1);
2214 remain_size
= min(size
+ count
, 1 << (seg_no
+ 1)) - size
;
2216 copy(((BYTE
**)this->segment
[seg_no
] + element_size
* (size
- ((1 << seg_no
) & ~1))), v
,
2218 if(seg_no
!= last_seg_no
)
2220 for(seg_no
++; seg_no
< last_seg_no
; seg_no
++)
2221 copy(this->segment
[seg_no
], v
, 1 << seg_no
);
2222 copy(this->segment
[last_seg_no
], v
, size
+ count
- (1 << last_seg_no
));
2227 /* ?_Internal_grow_to_at_least_with_result@_Concurrent_vector_base_v4@details@Concurrency@@IAEIIIP6AXPAXPBXI@Z1@Z */
2228 /* ?_Internal_grow_to_at_least_with_result@_Concurrent_vector_base_v4@details@Concurrency@@IEAA_K_K0P6AXPEAXPEBX0@Z2@Z */
2229 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_grow_to_at_least_with_result
, 20)
2230 MSVCP_size_t __thiscall
_Concurrent_vector_base_v4__Internal_grow_to_at_least_with_result(
2231 _Concurrent_vector_base_v4
*this, MSVCP_size_t count
, MSVCP_size_t element_size
,
2232 void (__cdecl
*copy
)(void*, const void*, MSVCP_size_t
), const void *v
)
2234 MSVCP_size_t size
, seg_no
, last_seg_no
, remain_size
;
2236 TRACE("(%p %ld %ld %p %p)\n", this, count
, element_size
, copy
, v
);
2238 _Concurrent_vector_base_v4__Internal_reserve(this, count
, element_size
,
2239 MSVCP_SIZE_T_MAX
/ element_size
);
2241 size
= this->early_size
;
2242 if(size
>= count
) return size
;
2243 } while(InterlockedCompareExchangeSizeT(&this->early_size
, count
, size
) != size
);
2245 seg_no
= size
? _vector_base_v4__Segment_index_of(size
- 1) : 0;
2246 last_seg_no
= _vector_base_v4__Segment_index_of(count
- 1);
2247 remain_size
= min(count
, 1 << (seg_no
+ 1)) - size
;
2249 copy(((BYTE
**)this->segment
[seg_no
] + element_size
* (size
- ((1 << seg_no
) & ~1))), v
,
2251 if(seg_no
!= last_seg_no
)
2253 for(seg_no
++; seg_no
< last_seg_no
; seg_no
++)
2254 copy(this->segment
[seg_no
], v
, 1 << seg_no
);
2255 copy(this->segment
[last_seg_no
], v
, count
- (1 << last_seg_no
));
2260 /* ?_Internal_push_back@_Concurrent_vector_base_v4@details@Concurrency@@IAEPAXIAAI@Z */
2261 /* ?_Internal_push_back@_Concurrent_vector_base_v4@details@Concurrency@@IEAAPEAX_KAEA_K@Z */
2262 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_push_back
, 12)
2263 void * __thiscall
_Concurrent_vector_base_v4__Internal_push_back(
2264 _Concurrent_vector_base_v4
*this, MSVCP_size_t element_size
, MSVCP_size_t
*idx
)
2266 MSVCP_size_t index
, seg
, segment_base
;
2269 TRACE("(%p %ld %p)\n", this, element_size
, idx
);
2272 index
= this->early_size
;
2273 _Concurrent_vector_base_v4__Internal_reserve(this, index
+ 1,
2274 element_size
, MSVCP_SIZE_T_MAX
/ element_size
);
2275 } while(InterlockedCompareExchangeSizeT(&this->early_size
, index
+ 1, index
) != index
);
2276 seg
= _vector_base_v4__Segment_index_of(index
);
2277 segment_base
= (seg
== 0) ? 0 : (1 << seg
);
2278 data
= (BYTE
*)this->segment
[seg
] + element_size
* (index
- segment_base
);
2284 /* ?_Internal_resize@_Concurrent_vector_base_v4@details@Concurrency@@IAEXIIIP6AXPAXI@ZP6AX0PBXI@Z2@Z */
2285 /* ?_Internal_resize@_Concurrent_vector_base_v4@details@Concurrency@@IEAAX_K00P6AXPEAX0@ZP6AX1PEBX0@Z3@Z */
2286 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_resize
, 28)
2287 void __thiscall
_Concurrent_vector_base_v4__Internal_resize(
2288 _Concurrent_vector_base_v4
*this, MSVCP_size_t resize
, MSVCP_size_t element_size
,
2289 MSVCP_size_t max_size
, void (__cdecl
*clear
)(void*, MSVCP_size_t
),
2290 void (__cdecl
*copy
)(void*, const void*, MSVCP_size_t
), const void *v
)
2292 MSVCP_size_t size
, seg_no
, end_seg_no
, clear_element
;
2294 TRACE("(%p %ld %ld %ld %p %p %p)\n", this, resize
, element_size
, max_size
, clear
, copy
, v
);
2296 if(resize
> max_size
) _vector_base_v4__Internal_throw_exception(this, 0);
2297 size
= this->early_size
;
2299 _Concurrent_vector_base_v4__Internal_grow_to_at_least_with_result(this,
2300 resize
, element_size
, copy
, v
);
2301 else if(resize
== 0)
2302 _Concurrent_vector_base_v4__Internal_clear(this, clear
);
2303 else if(resize
< size
)
2305 seg_no
= _vector_base_v4__Segment_index_of(size
- 1);
2306 end_seg_no
= _vector_base_v4__Segment_index_of(resize
- 1);
2307 clear_element
= size
- (seg_no
? 1 << seg_no
: 2);
2308 if(clear_element
> 0)
2309 clear(this->segment
[seg_no
], clear_element
);
2310 if(seg_no
) seg_no
--;
2311 for(; seg_no
> end_seg_no
; seg_no
--)
2312 clear(this->segment
[seg_no
], 1 << seg_no
);
2313 clear_element
= (1 << (end_seg_no
+ 1)) - resize
;
2314 if(clear_element
> 0)
2315 clear((BYTE
**)this->segment
[end_seg_no
] + element_size
* (resize
- ((1 << end_seg_no
) & ~1)),
2317 this->early_size
= resize
;
2321 /* ?_Internal_swap@_Concurrent_vector_base_v4@details@Concurrency@@IAEXAAV123@@Z */
2322 /* ?_Internal_swap@_Concurrent_vector_base_v4@details@Concurrency@@IEAAXAEAV123@@Z */
2323 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_swap
, 8)
2324 void __thiscall
_Concurrent_vector_base_v4__Internal_swap(
2325 _Concurrent_vector_base_v4
*this, _Concurrent_vector_base_v4
*v
)
2327 _Concurrent_vector_base_v4 temp
;
2329 TRACE("(%p %p)\n", this, v
);
2334 if(v
->segment
== this->storage
)
2335 v
->segment
= v
->storage
;
2336 if(this->segment
== v
->storage
)
2337 this->segment
= this->storage
;
2342 void __asm_dummy_vtables(void) {
2344 #if _MSVCP_VER == 100
2345 __ASM_VTABLE(iostream_category
,
2346 VTABLE_ADD_FUNC(custom_category_vector_dtor
)
2347 VTABLE_ADD_FUNC(custom_category_name
)
2348 VTABLE_ADD_FUNC(iostream_category_message
)
2349 VTABLE_ADD_FUNC(custom_category_default_error_condition
)
2350 VTABLE_ADD_FUNC(custom_category_equivalent
)
2351 VTABLE_ADD_FUNC(custom_category_equivalent_code
));
2352 __ASM_VTABLE(system_category
,
2353 VTABLE_ADD_FUNC(custom_category_vector_dtor
)
2354 VTABLE_ADD_FUNC(custom_category_name
)
2355 VTABLE_ADD_FUNC(custom_category_message
)
2356 VTABLE_ADD_FUNC(custom_category_default_error_condition
)
2357 VTABLE_ADD_FUNC(custom_category_equivalent
)
2358 VTABLE_ADD_FUNC(custom_category_equivalent_code
));
2359 __ASM_VTABLE(generic_category
,
2360 VTABLE_ADD_FUNC(custom_category_vector_dtor
)
2361 VTABLE_ADD_FUNC(custom_category_name
)
2362 VTABLE_ADD_FUNC(custom_category_message
)
2363 VTABLE_ADD_FUNC(custom_category_default_error_condition
)
2364 VTABLE_ADD_FUNC(custom_category_equivalent
)
2365 VTABLE_ADD_FUNC(custom_category_equivalent_code
));
2367 #if _MSVCP_VER >= 100
2368 __ASM_VTABLE(_Concurrent_queue_base_v4
,
2369 #if _MSVCP_VER >= 110
2370 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy
)
2372 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy
)
2373 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy
)
2374 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_vector_dtor
)
2375 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy
)
2376 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy
));
2377 __ASM_VTABLE(_Runtime_object
,
2378 VTABLE_ADD_FUNC(_Runtime_object__GetId
));
2380 #if _MSVCP_VER >= 110
2382 VTABLE_ADD_FUNC(_Pad__Go
));
2388 /*********************************************************************
2389 * __crtInitializeCriticalSectionEx (MSVCP140.@)
2391 BOOL CDECL
MSVCP__crtInitializeCriticalSectionEx(
2392 CRITICAL_SECTION
*cs
, DWORD spin_count
, DWORD flags
)
2394 TRACE("(%p %x %x)\n", cs
, spin_count
, flags
);
2395 return InitializeCriticalSectionEx(cs
, spin_count
, flags
);
2398 /*********************************************************************
2399 * __crtCreateEventExW (MSVCP140.@)
2401 HANDLE CDECL
MSVCP__crtCreateEventExW(
2402 SECURITY_ATTRIBUTES
*attribs
, LPCWSTR name
, DWORD flags
, DWORD access
)
2404 TRACE("(%p %s 0x%08x 0x%08x)\n", attribs
, debugstr_w(name
), flags
, access
);
2405 return CreateEventExW(attribs
, name
, flags
, access
);
2408 /*********************************************************************
2409 * __crtGetTickCount64 (MSVCP140.@)
2411 ULONGLONG CDECL
MSVCP__crtGetTickCount64(void)
2413 return GetTickCount64();
2416 /*********************************************************************
2417 * __crtGetCurrentProcessorNumber (MSVCP140.@)
2419 DWORD CDECL
MSVCP__crtGetCurrentProcessorNumber(void)
2421 return GetCurrentProcessorNumber();
2424 /*********************************************************************
2425 * __crtFlushProcessWriteBuffers (MSVCP140.@)
2427 VOID CDECL
MSVCP__crtFlushProcessWriteBuffers(void)
2429 return FlushProcessWriteBuffers();
2432 /*********************************************************************
2433 * __crtCreateSemaphoreExW (MSVCP140.@)
2435 HANDLE CDECL
MSVCP__crtCreateSemaphoreExW(
2436 SECURITY_ATTRIBUTES
*attribs
, LONG initial_count
, LONG max_count
, LPCWSTR name
,
2437 DWORD flags
, DWORD access
)
2439 TRACE("(%p %d %d %s 0x%08x 0x%08x)\n", attribs
, initial_count
, max_count
, debugstr_w(name
),
2441 return CreateSemaphoreExW(attribs
, initial_count
, max_count
, name
, flags
, access
);
2444 /*********************************************************************
2445 * __crtCreateThreadpoolTimer (MSVCP140.@)
2447 PTP_TIMER CDECL
MSVCP__crtCreateThreadpoolTimer(PTP_TIMER_CALLBACK callback
,
2448 PVOID userdata
, TP_CALLBACK_ENVIRON
*environment
)
2450 TRACE("(%p %p %p)\n", callback
, userdata
, environment
);
2451 return CreateThreadpoolTimer(callback
, userdata
, environment
);
2454 /*********************************************************************
2455 * __crtCloseThreadpoolTimer (MSVCP140.@)
2457 VOID CDECL
MSVCP__crtCloseThreadpoolTimer(TP_TIMER
*timer
)
2459 TRACE("(%p)\n", timer
);
2460 CloseThreadpoolTimer(timer
);
2463 /*********************************************************************
2464 * __crtSetThreadpoolTimer (MSVCP140.@)
2466 VOID CDECL
MSVCP__crtSetThreadpoolTimer(TP_TIMER
*timer
,
2467 FILETIME
*due_time
, DWORD period
, DWORD window_length
)
2469 TRACE("(%p %p 0x%08x 0x%08x)\n", timer
, due_time
, period
, window_length
);
2470 return SetThreadpoolTimer(timer
, due_time
, period
, window_length
);
2473 /*********************************************************************
2474 * __crtWaitForThreadpoolTimerCallbacks (MSVCP140.@)
2476 VOID CDECL
MSVCP__crtWaitForThreadpoolTimerCallbacks(TP_TIMER
*timer
, BOOL cancel
)
2478 TRACE("(%p %d)\n", timer
, cancel
);
2479 WaitForThreadpoolTimerCallbacks(timer
, cancel
);
2482 /*********************************************************************
2483 * __crtCreateThreadpoolWait (MSVCP140.@)
2485 PTP_WAIT CDECL
MSVCP__crtCreateThreadpoolWait(PTP_WAIT_CALLBACK callback
,
2486 PVOID userdata
, TP_CALLBACK_ENVIRON
*environment
)
2488 TRACE("(%p %p %p)\n", callback
, userdata
, environment
);
2489 return CreateThreadpoolWait(callback
, userdata
, environment
);
2492 /*********************************************************************
2493 * __crtCloseThreadpoolWait (MSVCP140.@)
2495 VOID CDECL
MSVCP__crtCloseThreadpoolWait(TP_WAIT
*wait
)
2497 TRACE("(%p)\n", wait
);
2498 CloseThreadpoolWait(wait
);
2501 /*********************************************************************
2502 * __crtSetThreadpoolWait (MSVCP140.@)
2504 VOID CDECL
MSVCP__crtSetThreadpoolWait(TP_WAIT
*wait
, HANDLE handle
, FILETIME
*due_time
)
2506 TRACE("(%p %p %p)\n", wait
, handle
, due_time
);
2507 return SetThreadpoolWait(wait
, handle
, due_time
);
2510 /*********************************************************************
2511 * __crtFreeLibraryWhenCallbackReturns (MSVCP140.@)
2513 VOID CDECL
MSVCP__crtFreeLibraryWhenCallbackReturns(PTP_CALLBACK_INSTANCE instance
, HMODULE mod
)
2515 TRACE("(%p %p)\n", instance
, mod
);
2516 FreeLibraryWhenCallbackReturns(instance
, mod
);
2519 /* ?_Execute_once@std@@YAHAAUonce_flag@1@P6GHPAX1PAPAX@Z1@Z */
2520 /* ?_Execute_once@std@@YAHAEAUonce_flag@1@P6AHPEAX1PEAPEAX@Z1@Z */
2521 BOOL __cdecl
_Execute_once(INIT_ONCE
*flag
, PINIT_ONCE_FN func
, void *param
)
2523 return InitOnceExecuteOnce(flag
, func
, param
, NULL
);
2526 #if _MSVCP_VER >= 100
2527 void init_misc(void *base
)
2530 #if _MSVCP_VER == 100
2531 init_error_category_rtti(base
);
2532 init_iostream_category_rtti(base
);
2533 init_system_category_rtti(base
);
2534 init_generic_category_rtti(base
);
2536 #if _MSVCP_VER >= 100
2537 init__Concurrent_queue_base_v4_rtti(base
);
2538 init__Runtime_object_rtti(base
);
2540 #if _MSVCP_VER >= 110
2541 init__Pad_rtti(base
);
2545 #if _MSVCP_VER == 100
2546 iostream_category_ctor(&iostream_category
);
2547 system_category_ctor(&system_category
);
2548 generic_category_ctor(&generic_category
);
2552 void free_misc(void)
2554 #if _MSVCP_VER >= 110
2556 NtClose(keyed_event
);
2557 HeapFree(GetProcessHeap(), 0, broadcast_at_thread_exit
.to_broadcast
);
2562 #if _MSVCP_VER >= 140
2563 LONGLONG __cdecl
_Query_perf_counter(void)
2566 QueryPerformanceCounter(&li
);
2570 LONGLONG __cdecl
_Query_perf_frequency(void)
2573 QueryPerformanceFrequency(&li
);
2578 void __cdecl
threads__Mtx_new(void **mtx
)
2580 *mtx
= MSVCRT_operator_new(sizeof(CRITICAL_SECTION
));
2581 InitializeCriticalSection(*mtx
);
2584 void __cdecl
threads__Mtx_delete(void *mtx
)
2586 DeleteCriticalSection(mtx
);
2589 void __cdecl
threads__Mtx_lock(void *mtx
)
2591 EnterCriticalSection(mtx
);
2594 void __cdecl
threads__Mtx_unlock(void *mtx
)
2596 LeaveCriticalSection(mtx
);
2599 #if _MSVCP_VER >= 110
2600 static LONG shared_ptr_lock
;
2602 void __cdecl
_Lock_shared_ptr_spin_lock(void)
2606 while(InterlockedCompareExchange(&shared_ptr_lock
, 1, 0) != 0) {
2614 void __cdecl
_Unlock_shared_ptr_spin_lock(void)
2616 shared_ptr_lock
= 0;
2620 #if _MSVCP_VER >= 100
2621 /* ?is_current_task_group_canceling@Concurrency@@YA_NXZ */
2622 MSVCP_bool __cdecl
is_current_task_group_canceling(void)
2624 return Context_IsCurrentTaskCollectionCanceling();
2627 /* ?_GetCombinableSize@details@Concurrency@@YAIXZ */
2628 /* ?_GetCombinableSize@details@Concurrency@@YA_KXZ */
2629 MSVCP_size_t __cdecl
_GetCombinableSize(void)
2636 #if _MSVCP_VER >= 140
2640 } task_continuation_context
;
2642 /* ??0task_continuation_context@Concurrency@@AAE@XZ */
2643 /* ??0task_continuation_context@Concurrency@@AEAA@XZ */
2644 DEFINE_THISCALL_WRAPPER(task_continuation_context_ctor
, 4)
2645 task_continuation_context
* __thiscall
task_continuation_context_ctor(task_continuation_context
*this)
2647 TRACE("(%p)\n", this);
2648 memset(this, 0, sizeof(*this));
2653 const vtable_ptr
*vtable
;
2654 void (__cdecl
*func
)(void);
2658 } function_void_cdecl_void
;
2660 /* ?_Assign@_ContextCallback@details@Concurrency@@AAEXPAX@Z */
2661 /* ?_Assign@_ContextCallback@details@Concurrency@@AEAAXPEAX@Z */
2662 DEFINE_THISCALL_WRAPPER(_ContextCallback__Assign
, 8)
2663 void __thiscall
_ContextCallback__Assign(void *this, void *v
)
2665 TRACE("(%p %p)\n", this, v
);
2668 #define call_function_do_call(this) CALL_VTBL_FUNC(this, 8, void, (function_void_cdecl_void*), (this))
2669 #define call_function_do_clean(this,b) CALL_VTBL_FUNC(this, 16, void, (function_void_cdecl_void*,MSVCP_bool), (this, b))
2670 /* ?_CallInContext@_ContextCallback@details@Concurrency@@QBEXV?$function@$$A6AXXZ@std@@_N@Z */
2671 /* ?_CallInContext@_ContextCallback@details@Concurrency@@QEBAXV?$function@$$A6AXXZ@std@@_N@Z */
2672 DEFINE_THISCALL_WRAPPER(_ContextCallback__CallInContext
, 48)
2673 void __thiscall
_ContextCallback__CallInContext(const void *this, function_void_cdecl_void func
, MSVCP_bool b
)
2675 TRACE("(%p %p %x)\n", this, func
.func
, b
);
2676 call_function_do_call(func
.this);
2677 call_function_do_clean(func
.this, func
.this!=&func
);
2680 /* ?_Capture@_ContextCallback@details@Concurrency@@AAEXXZ */
2681 /* ?_Capture@_ContextCallback@details@Concurrency@@AEAAXXZ */
2682 DEFINE_THISCALL_WRAPPER(_ContextCallback__Capture
, 4)
2683 void __thiscall
_ContextCallback__Capture(void *this)
2685 TRACE("(%p)\n", this);
2688 /* ?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ */
2689 /* ?_Reset@_ContextCallback@details@Concurrency@@AEAAXXZ */
2690 DEFINE_THISCALL_WRAPPER(_ContextCallback__Reset
, 4)
2691 void __thiscall
_ContextCallback__Reset(void *this)
2693 TRACE("(%p)\n", this);
2696 /* ?_IsCurrentOriginSTA@_ContextCallback@details@Concurrency@@CA_NXZ */
2697 MSVCP_bool __cdecl
_ContextCallback__IsCurrentOriginSTA(void *this)
2699 TRACE("(%p)\n", this);
2704 /*_Task_impl_base*/void *task
;
2705 MSVCP_bool scheduled
;
2709 /* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2710 /* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2711 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogCancelTask
, 4)
2712 void __thiscall
_TaskEventLogger__LogCancelTask(_TaskEventLogger
*this)
2714 TRACE("(%p)\n", this);
2717 /* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z */
2718 /* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QEAAX_N@Z */
2719 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogScheduleTask
, 8)
2720 void __thiscall
_TaskEventLogger__LogScheduleTask(_TaskEventLogger
*this, MSVCP_bool continuation
)
2722 TRACE("(%p %x)\n", this, continuation
);
2725 /* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2726 /* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2727 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskCompleted
, 4)
2728 void __thiscall
_TaskEventLogger__LogTaskCompleted(_TaskEventLogger
*this)
2730 TRACE("(%p)\n", this);
2733 /* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2734 /* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2735 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskExecutionCompleted
, 4)
2736 void __thiscall
_TaskEventLogger__LogTaskExecutionCompleted(_TaskEventLogger
*this)
2738 TRACE("(%p)\n", this);
2741 /* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2742 /* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2743 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemCompleted
, 4)
2744 void __thiscall
_TaskEventLogger__LogWorkItemCompleted(_TaskEventLogger
*this)
2746 TRACE("(%p)\n", this);
2749 /* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2750 /* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2751 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemStarted
, 4)
2752 void __thiscall
_TaskEventLogger__LogWorkItemStarted(_TaskEventLogger
*this)
2754 TRACE("(%p)\n", this);
2759 void (__cdecl
*callback
)(void*);
2761 } _Threadpool_chore
;
2763 /* ?_Reschedule_chore@details@Concurrency@@YAHPBU_Threadpool_chore@12@@Z */
2764 /* ?_Reschedule_chore@details@Concurrency@@YAHPEBU_Threadpool_chore@12@@Z */
2765 int __cdecl
_Reschedule_chore(const _Threadpool_chore
*chore
)
2767 TRACE("(%p)\n", chore
);
2769 SubmitThreadpoolWork(chore
->work
);
2773 static void WINAPI
threadpool_callback(PTP_CALLBACK_INSTANCE instance
, void *context
, PTP_WORK work
)
2775 _Threadpool_chore
*chore
= context
;
2776 TRACE("calling chore callback: %p\n", chore
);
2777 if (chore
->callback
)
2778 chore
->callback(chore
->arg
);
2781 /* ?_Schedule_chore@details@Concurrency@@YAHPAU_Threadpool_chore@12@@Z */
2782 /* ?_Schedule_chore@details@Concurrency@@YAHPEAU_Threadpool_chore@12@@Z */
2783 int __cdecl
_Schedule_chore(_Threadpool_chore
*chore
)
2785 TRACE("(%p)\n", chore
);
2787 chore
->work
= CreateThreadpoolWork(threadpool_callback
, chore
, NULL
);
2788 /* FIXME: what should be returned in case of error */
2792 return _Reschedule_chore(chore
);
2795 /* ?_Release_chore@details@Concurrency@@YAXPAU_Threadpool_chore@12@@Z */
2796 /* ?_Release_chore@details@Concurrency@@YAXPEAU_Threadpool_chore@12@@Z */
2797 void __cdecl
_Release_chore(_Threadpool_chore
*chore
)
2799 TRACE("(%p)\n", chore
);
2801 if(!chore
->work
) return;
2802 CloseThreadpoolWork(chore
->work
);
2807 #if _MSVCP_VER >= 110 && _MSVCP_VER <= 120
2812 /* ?_1@placeholders@std@@3V?$_Ph@$00@2@A */
2813 /* ?_20@placeholders@std@@3V?$_Ph@$0BE@@2@A */
2814 _Ph _Ph_1
= {0}, _Ph_2
= {0}, _Ph_3
= {0}, _Ph_4
= {0}, _Ph_5
= {0};
2815 _Ph _Ph_6
= {0}, _Ph_7
= {0}, _Ph_8
= {0}, _Ph_9
= {0}, _Ph_10
= {0};
2816 _Ph _Ph_11
= {0}, _Ph_12
= {0}, _Ph_13
= {0}, _Ph_14
= {0}, _Ph_15
= {0};
2817 _Ph _Ph_16
= {0}, _Ph_17
= {0}, _Ph_18
= {0}, _Ph_19
= {0}, _Ph_20
= {0};
2820 #if _MSVCP_VER >= 140
2821 /* ?_IsNonBlockingThread@_Task_impl_base@details@Concurrency@@SA_NXZ */
2822 MSVCP_bool __cdecl
_Task_impl_base__IsNonBlockingThread(void)
2829 #if _MSVCP_VER >= 110
2830 /* ?_Syserror_map@std@@YAPBDH@Z */
2831 /* ?_Syserror_map@std@@YAPEBDH@Z */
2832 const char* __cdecl
_Syserror_map(int err
)
2836 TRACE("(%d)\n", err
);
2838 for(i
= 0; i
< ARRAY_SIZE(syserror_map
); i
++)
2840 if(syserror_map
[i
].err
== err
)
2841 return syserror_map
[i
].str
;
2847 #if _MSVCP_VER >= 140
2848 /* ?_Winerror_message@std@@YAKKPADK@Z */
2849 /* ?_Winerror_message@std@@YAKKPEADK@Z */
2850 ULONG __cdecl
_Winerror_message(ULONG err
, char *buf
, ULONG size
)
2852 TRACE("(%u %p %u)\n", err
, buf
, size
);
2854 return FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
,
2855 NULL
, err
, 0, buf
, size
, NULL
);
2858 /* ?_Winerror_map@std@@YAHH@Z */
2859 int __cdecl
_Winerror_map(int err
)
2861 int low
= 0, high
= ARRAY_SIZE(winerror_map
) - 1, mid
;
2865 mid
= (low
+ high
) / 2;
2867 if(err
== winerror_map
[mid
].winerr
)
2868 return winerror_map
[mid
].doserr
;
2869 if(err
> winerror_map
[mid
].winerr
)