blob: bb56879732b3514ab90660ade97ea0e9adc6be85 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PERIDOT_LIB_UTIL_PSEUDO_DIR_SERVER_H_
#define PERIDOT_LIB_UTIL_PSEUDO_DIR_SERVER_H_
#include <lib/async-loop/cpp/loop.h>
#include <lib/fsl/io/fd.h>
#include <lib/vfs/cpp/pseudo_dir.h>
#include <src/lib/files/unique_fd.h>
#include <condition_variable>
#include <mutex>
#include <thread>
namespace modular {
// Given a pseudo directory, spins up a thread and serves Directory operations
// over it. This utility is useful for making thread-blocking posix calls to the
// given PseudoDir, which needs its owning thread to not be blocked to service
// directory calls.
//
// The directory is accessible using |OpenAt()|.
//
// This class is thread-unsafe.
class PseudoDirServer final {
public:
// Spins up a thread to serve the given |pseudo_dir| directory calls over.
// This constructor blocks the current thread until the child thread has
// initialized.
//
// Requires that the calling thread has an async dispatcher.
PseudoDirServer(std::unique_ptr<vfs::PseudoDir> pseudo_dir);
// This destructor blocks the current thread until the child thread exits.
~PseudoDirServer();
// Opens a read-only FD at |path|. Path must not begin with '/'.
fxl::UniqueFD OpenAt(std::string path);
private:
// This method is the handler for a new thread. It lets the owning thread
// know that it has started and serves a directory requests. The thread is
// exited when this object is destroyed.
void StartThread(fidl::InterfaceRequest<fuchsia::io::Directory> request);
std::unique_ptr<vfs::PseudoDir> pseudo_dir_;
// The directory connection we that |pseudo_dir| serves over in a differnt
// thread.
fuchsia::io::DirectoryPtr dir_;
// The mutex & condition variable are used by the new thread (owned by
// |serving_thread_|) to signal to the owning thread that it has started,
// making it safe to then access |thread_loop_|.
std::mutex ready_mutex_;
std::condition_variable thread_loop_ready_;
async::Loop* thread_loop_ = nullptr; // serving thread's loop.
std::thread serving_thread_;
};
} // namespace modular
#endif // PERIDOT_LIB_UTIL_PSEUDO_DIR_SERVER_H_