audreyt/node-webworker-threads 2176
Lightweight Web Worker API implementation with native threads
A client/server web application framework built on Express and Backbone
kkaefer/DEPRECATED-node-zlib 47
DEPRECATED – Simple, synchronous deflate/inflate for node.js buffers
a version of gdal2tiles with MapBox support
Format dates in JavaScript
developmentseed/backbone-dirty 10
Use node-dirty for Model persistence with backbone.js
Experimental Storage of Backbone Models/Collections in Redis. NOTE: Abandoned course project. Do not use in production.
Browse My Tweets
Drupal based Intranet
TDD framework for node -- high speed parallel testing!
Pull request review commentmapbox/mapbox-base
[weak] Introduce WeakPtrFactory::invalidateWeakPtrs()
class WeakPtrSharedData { WeakPtrSharedData() = default; void sharedLock() {- assert(valid());- sharedLocks_++;+ std::size_t noLocks = sharedLocks_;+ std::size_t incremented;+ do {+ if (noLocks == kInvalidValue) return;+ incremented = noLocks + 1;+ // `compare_exchange_weak()` is invoked in a cycle to handle the case,+ // if another thread has just modified `sharedLocks_` (so that it is not+ // equal to `noLocks` any more). We early return, if `sharedLocks_` became+ // equal to `kInvalidValue`.+ } while (!sharedLocks_.compare_exchange_weak(noLocks, incremented)); } void sharedUnlock() {- assert(valid());- assert(sharedLocks_ > 0u);- sharedLocks_--;+ std::size_t noLocks = sharedLocks_;+ std::size_t decremented;+ do {+ if (noLocks == kInvalidValue) return;+ decremented = noLocks - 1;
(I realize that if used correctly, this situation will not occur, since a precondition of this function is that sharedLocks_ is > 0)
comment created time in 2 months
Pull request review commentmapbox/mapbox-base
[weak] Introduce WeakPtrFactory::invalidateWeakPtrs()
class WeakPtrSharedData { WeakPtrSharedData() = default; void sharedLock() {- assert(valid());- sharedLocks_++;+ std::size_t noLocks = sharedLocks_;+ std::size_t incremented;+ do {+ if (noLocks == kInvalidValue) return;+ incremented = noLocks + 1;+ // `compare_exchange_weak()` is invoked in a cycle to handle the case,+ // if another thread has just modified `sharedLocks_` (so that it is not+ // equal to `noLocks` any more). We early return, if `sharedLocks_` became+ // equal to `kInvalidValue`.+ } while (!sharedLocks_.compare_exchange_weak(noLocks, incremented)); } void sharedUnlock() {- assert(valid());- assert(sharedLocks_ > 0u);- sharedLocks_--;+ std::size_t noLocks = sharedLocks_;+ std::size_t decremented;+ do {+ if (noLocks == kInvalidValue) return;+ decremented = noLocks - 1;+ assert(decremented >= 0u);
This is always true, since size_t is unsigned.
comment created time in 2 months
Pull request review commentmapbox/mapbox-base
[weak] Introduce WeakPtrFactory::invalidateWeakPtrs()
class WeakPtrSharedData { WeakPtrSharedData() = default; void sharedLock() {- assert(valid());- sharedLocks_++;+ std::size_t noLocks = sharedLocks_;+ std::size_t incremented;+ do {+ if (noLocks == kInvalidValue) return;+ incremented = noLocks + 1;+ // `compare_exchange_weak()` is invoked in a cycle to handle the case,+ // if another thread has just modified `sharedLocks_` (so that it is not+ // equal to `noLocks` any more). We early return, if `sharedLocks_` became+ // equal to `kInvalidValue`.+ } while (!sharedLocks_.compare_exchange_weak(noLocks, incremented)); } void sharedUnlock() {- assert(valid());- assert(sharedLocks_ > 0u);- sharedLocks_--;+ std::size_t noLocks = sharedLocks_;+ std::size_t decremented;+ do {+ if (noLocks == kInvalidValue) return;+ decremented = noLocks - 1;
This will overflow if noLocks == 0.
comment created time in 2 months
Pull request review commentmapbox/mapbox-base
[weak] Introduce WeakPtrFactory::invalidateWeakPtrs()
class WeakPtrFactory final { }; } + /**+ * @brief Invalidates all existing weak pointers.+ *+ * This method is particularly useful, when \c T class has a user-defined destructor,+ * that makes the wrapped instance invalid even before entering the \c WeakPtrFactory+ * destructor.+ * In this case, clients *MUST* explicitly call \c invalidateWeakPtrs() before freeing any resources.+ *+ * Note: After \c invalidateWeakPtrs() is called, \c makeWeakPtr() returns empty weak pointers.+ */+ void invalidateWeakPtrs() {+ if (strong_) strong_->invalidate();+ strong_.reset();
This could still fail:
Thread A calls invalidateWeakPtr in WeakPtrFactory's destructor. It proceeds until after the strong_->invalidate(), but before the strong_.reset() call, and gets preempted. At this point, sharedLocks_ is set to kInvalidValue aka numeric_limits<std::size_t>::max.
Thread B has a WeakPtr. It gets scheduled to run, and calls .lock(), which acquires a std::shared_ptr of WeakPtrSharedData. This is still possible, since the object is still strongly held by the WeakPtrFactory. lock() then proceeds to call strong->sharedLock(). While there's an assert in that function that will terminate the program in debug builds, sharedLock will happily increment the sharedLocks_ atomic (which will now be 0 since it overflowed, and unsigned integer overflow is not UB). That means strong->valid() will also return true, and we'll return a valid WeakPtrGuard handle. 💥
comment created time in 2 months
starteddebauchee/barrier
started time in 3 months