blob: 17efc5cd324def6d82cf89e6d9984ef2460365f6 [file] [log] [blame]
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_PORTS_SKMUTEX_STARBOARD_H_
#define COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_PORTS_SKMUTEX_STARBOARD_H_
#include "starboard/mutex.h"
#include "starboard/thread.h"
// A Starboard-based implementation of mutex, with support for static
// initialization without initializer/finalizer, which can cause race
// conditions at application exit.
// A SkBaseMutex is a POD structure that can be directly initialized
// at declaration time with SK_DECLARE_STATIC/GLOBAL_MUTEX. This avoids the
// generation of a static initializer/finalizer.
struct SkBaseMutex {
void acquire() {
SbMutexAcquire(&mutex_);
SetAcquired();
}
void release() {
SetReleased();
SbMutexRelease(&mutex_);
}
void assertHeld() { AssertAcquired(); }
SbMutex mutex_;
#ifdef SK_DEBUG
void Init() {
holding_thread_ = kSbThreadInvalid;
initialized_ = true;
}
void SetAcquired() {
if (!initialized_) {
Init();
}
SB_DCHECK(holding_thread_ == kSbThreadInvalid);
holding_thread_ = SbThreadGetCurrent();
}
void SetReleased() {
SB_DCHECK(holding_thread_ == SbThreadGetCurrent());
holding_thread_ = kSbThreadInvalid;
}
void AssertAcquired() const {
SkASSERT(initialized_ && holding_thread_ != kSbThreadInvalid);
}
// |initialized_| will be default-initialized to |false| by the POD-style
// initializer.
bool initialized_;
SbThread holding_thread_;
#else
void Init() {}
void SetAcquired() {}
void SetReleased() {}
void AssertAcquired() const {}
#endif // SK_DEBUG
};
// A mutex that requires to be initialized through normal C++ construction,
// i.e. when it's a member of another class, or allocated on the heap.
class SkMutex : public SkBaseMutex {
public:
SkMutex() {
Init();
SbMutexCreate(&mutex_);
}
~SkMutex() { SbMutexDestroy(&mutex_); }
};
#define SK_BASE_MUTEX_INIT \
{ SB_MUTEX_INITIALIZER }
// Using POD-style initialization prevents the generation of a static
// initializer.
//
// Without magic statics there are no thread safety guarantees on initialization
// of local statics (even POD). As a result, it is illegal to use
// SK_DECLARE_STATIC_MUTEX in a function.
//
// Because SkBaseMutex is not a primitive, a static SkBaseMutex cannot be
// initialized in a class with this macro.
#define SK_DECLARE_STATIC_MUTEX(name) \
namespace {} \
static SkBaseMutex name = SK_BASE_MUTEX_INIT
#endif // COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_PORTS_SKMUTEX_STARBOARD_H_