chromium/native_client_sdk/src/libraries/nacl_io/stream/stream_fs.cc

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "nacl_io/stream/stream_fs.h"

#include <errno.h>

#include "nacl_io/ossocket.h"
#include "nacl_io/pepper_interface.h"

namespace nacl_io {

void DispatchStart(void* work_ptr, int32_t val) {
  StreamFs::Work* work = static_cast<StreamFs::Work*>(work_ptr);

  // Delete if it fails to Start, Run will never get called.
  if (!work->Start(val))
    delete work;
}

void DispatchRun(void* work_ptr, int32_t val) {
  StreamFs::Work* work = static_cast<StreamFs::Work*>(work_ptr);

  work->Run(val);
  delete work;
}

void* StreamFs::StreamThreadThunk(void* fs_ptr) {
  StreamFs* filesystem = static_cast<StreamFs*>(fs_ptr);
  filesystem->StreamThread();
  return NULL;
}

// All work is done via completions callbacks from posted work.
void StreamFs::StreamThread() {
  {
    AUTO_LOCK(message_lock_)
    message_loop_ =
        ppapi_->GetMessageLoopInterface()->Create(ppapi()->GetInstance());
    ppapi_->GetMessageLoopInterface()->AttachToCurrentThread(message_loop_);
    pthread_cond_broadcast(&message_cond_);
  }

  // Run loop until Quit is posted.
  ppapi_->GetMessageLoopInterface()->Run(message_loop_);
}

PP_CompletionCallback StreamFs::GetStartCompletion(Work* work) {
  return PP_MakeCompletionCallback(DispatchStart, work);
}

PP_CompletionCallback StreamFs::GetRunCompletion(Work* work) {
  return PP_MakeCompletionCallback(DispatchRun, work);
}

// Place enqueue onto the socket thread.
void StreamFs::EnqueueWork(Work* work) {
  if (message_loop_ == 0) {
    AUTO_LOCK(message_lock_);

    if (message_loop_ == 0) {
      pthread_t thread;
      pthread_create(&thread, NULL, StreamThreadThunk, this);
    }

    while (message_loop_ == 0)
      pthread_cond_wait(&message_cond_, message_lock_.mutex());
  }

  PP_CompletionCallback cb = PP_MakeCompletionCallback(DispatchStart, work);
  ppapi_->GetMessageLoopInterface()->PostWork(message_loop_, cb, 0);
}

StreamFs::StreamFs() : message_loop_(0) {
  pthread_cond_init(&message_cond_, NULL);
}

StreamFs::~StreamFs() {
  if (message_loop_) {
    ppapi_->GetMessageLoopInterface()->PostQuit(message_loop_, PP_TRUE);
    ppapi_->ReleaseResource(message_loop_);
  }
  pthread_cond_destroy(&message_cond_);
}

Error StreamFs::OpenWithMode(const Path& path, int o_flags, mode_t mode,
                             ScopedNode* out_node) {
  return EACCES;
}

Error StreamFs::Unlink(const Path& path) {
  return EACCES;
}

Error StreamFs::Mkdir(const Path& path, int permissions) {
  return EACCES;
}

Error StreamFs::Rmdir(const Path& path) {
  return EACCES;
}

Error StreamFs::Remove(const Path& path) {
  return EACCES;
}

Error StreamFs::Rename(const Path& path, const Path& newpath) {
  return EACCES;
}

}  // namespace nacl_io