Leveldb Windows port by Edouard Alligand, adapted for MingW by me.

This commit is contained in:
justmoon
2012-07-21 14:54:55 +02:00
committed by Pieter Wuille
parent 5e650d6d2d
commit 94a50fb339
8 changed files with 1106 additions and 33 deletions

View File

@@ -14,6 +14,8 @@
# include "port/port_posix.h"
#elif defined(LEVELDB_PLATFORM_CHROMIUM)
# include "port/port_chromium.h"
#elif defined(LEVELDB_PLATFORM_WINDOWS)
# include "port/port_win.h"
#endif
#endif // STORAGE_LEVELDB_PORT_PORT_H_

View File

@@ -0,0 +1,182 @@
// LevelDB Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
// See port_example.h for documentation for the following types/functions.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the University of California, Berkeley nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#include "port/port_win.h"
#include <windows.h>
#include <cassert>
namespace leveldb {
namespace port {
Mutex::Mutex() :
mutex_(::CreateMutex(NULL, FALSE, NULL)) {
assert(mutex_);
}
Mutex::~Mutex() {
assert(mutex_);
::CloseHandle(mutex_);
}
void Mutex::Lock() {
assert(mutex_);
::WaitForSingleObject(mutex_, INFINITE);
}
void Mutex::Unlock() {
assert(mutex_);
::ReleaseMutex(mutex_);
}
void Mutex::AssertHeld() {
assert(mutex_);
assert(1);
}
CondVar::CondVar(Mutex* mu) :
waiting_(0),
mu_(mu),
sema_(::CreateSemaphore(NULL, 0, 0x7fffffff, NULL)),
event_(::CreateEvent(NULL, FALSE, FALSE, NULL)),
broadcasted_(false){
assert(mu_);
}
CondVar::~CondVar() {
::CloseHandle(sema_);
::CloseHandle(event_);
}
void CondVar::Wait() {
wait_mtx_.Lock();
++waiting_;
assert(waiting_ > 0);
wait_mtx_.Unlock();
::SignalObjectAndWait(mu_->mutex_, sema_, INFINITE, FALSE);
wait_mtx_.Lock();
bool last = broadcasted_ && (--waiting_ == 0);
assert(waiting_ >= 0);
wait_mtx_.Unlock();
// we leave this function with the mutex held
if (last)
{
::SignalObjectAndWait(event_, mu_->mutex_, INFINITE, FALSE);
}
else
{
::WaitForSingleObject(mu_->mutex_, INFINITE);
}
}
void CondVar::Signal() {
wait_mtx_.Lock();
bool waiters = waiting_ > 0;
wait_mtx_.Unlock();
if (waiters)
{
::ReleaseSemaphore(sema_, 1, 0);
}
}
void CondVar::SignalAll() {
wait_mtx_.Lock();
broadcasted_ = (waiting_ > 0);
if (broadcasted_)
{
// release all
::ReleaseSemaphore(sema_, waiting_, 0);
wait_mtx_.Unlock();
::WaitForSingleObject(event_, INFINITE);
broadcasted_ = false;
}
else
{
wait_mtx_.Unlock();
}
}
AtomicPointer::AtomicPointer(void* v) {
Release_Store(v);
}
void* AtomicPointer::Acquire_Load() const {
void * p = nullptr;
InterlockedExchangePointer(&p, rep_);
return p;
}
void AtomicPointer::Release_Store(void* v) {
InterlockedExchangePointer(&rep_, v);
}
void* AtomicPointer::NoBarrier_Load() const {
return rep_;
}
void AtomicPointer::NoBarrier_Store(void* v) {
rep_ = v;
}
enum InitializationState
{
Uninitialized = 0,
Running = 1,
Initialized = 2
};
void InitOnce(OnceType* once, void (*initializer)()) {
static_assert(Uninitialized == LEVELDB_ONCE_INIT, "Invalid uninitialized state value");
InitializationState state = static_cast<InitializationState>(InterlockedCompareExchange(once, Running, Uninitialized));
if (state == Uninitialized) {
initializer();
*once = Initialized;
}
if (state == Running) {
while(*once != Initialized) {
Sleep(0); // yield
}
}
assert(*once == Initialized);
}
}
}

161
src/leveldb/port/port_win.h Normal file
View File

@@ -0,0 +1,161 @@
// LevelDB Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
// See port_example.h for documentation for the following types/functions.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the University of California, Berkeley nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef STORAGE_LEVELDB_PORT_PORT_WIN_H_
#define STORAGE_LEVELDB_PORT_PORT_WIN_H_
#ifdef _MSC_VER
#define snprintf _snprintf
#define close _close
#define fread_unlocked _fread_nolock
#endif
#ifdef SNAPPY
#include <snappy/snappy.h>
#endif
#include <string>
#include <stdint.h>
namespace leveldb {
namespace port {
// Windows is little endian (for now :p)
static const bool kLittleEndian = true;
class CondVar;
class Mutex {
public:
Mutex();
~Mutex();
void Lock();
void Unlock();
void AssertHeld();
private:
friend class CondVar;
// critical sections are more efficient than mutexes
// but they are not recursive and can only be used to synchronize threads within the same process
// additionnaly they cannot be used with SignalObjectAndWait that we use for CondVar
// we use opaque void * to avoid including windows.h in port_win.h
void * mutex_;
// No copying
Mutex(const Mutex&);
void operator=(const Mutex&);
};
// the Win32 API offers a dependable condition variable mechanism, but only starting with
// Windows 2008 and Vista
// no matter what we will implement our own condition variable with a semaphore
// implementation as described in a paper written by Douglas C. Schmidt and Irfan Pyarali
class CondVar {
public:
explicit CondVar(Mutex* mu);
~CondVar();
void Wait();
void Signal();
void SignalAll();
private:
Mutex* mu_;
Mutex wait_mtx_;
long waiting_;
void * sema_;
void * event_;
bool broadcasted_;
};
// Storage for a lock-free pointer
class AtomicPointer {
private:
void * rep_;
public:
AtomicPointer() : rep_(nullptr) { }
explicit AtomicPointer(void* v);
void* Acquire_Load() const;
void Release_Store(void* v);
void* NoBarrier_Load() const;
void NoBarrier_Store(void* v);
};
typedef volatile long OnceType;
#define LEVELDB_ONCE_INIT (0)
extern void InitOnce(OnceType* once, void (*initializer)());
inline bool Snappy_Compress(const char* input, size_t length,
::std::string* output) {
#ifdef SNAPPY
output->resize(snappy::MaxCompressedLength(length));
size_t outlen;
snappy::RawCompress(input, length, &(*output)[0], &outlen);
output->resize(outlen);
return true;
#endif
return false;
}
inline bool Snappy_GetUncompressedLength(const char* input, size_t length,
size_t* result) {
#ifdef SNAPPY
return snappy::GetUncompressedLength(input, length, result);
#else
return false;
#endif
}
inline bool Snappy_Uncompress(const char* input, size_t length,
char* output) {
#ifdef SNAPPY
return snappy::RawUncompress(input, length, output);
#else
return false;
#endif
}
inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
return false;
}
}
}
#endif // STORAGE_LEVELDB_PORT_PORT_WIN_H_