Files
tubestation/ipc/glue/DataPipe.h
serge-sans-paille bf3516e81e Bug 1964489 - Avoid duplication in NS_DECLARE_STATIC_IID_ACCESSOR / NS_DEFINE_STATIC_IID_ACCESSOR r=nika,necko-reviewers,media-playback-reviewers,places-reviewers,win-reviewers,dom-storage-reviewers,xpcom-reviewers,gstoll,janv,emilio,padenot,valentin,asuth
In modern C++, static constexpr member variables are automatically
inline (aka weak) so the template trick is not needed. This also avoid
duplication and reduces the amount of parsed code. No impact on
generated binary (actually: smaller debuginfo, close to identical
binary).

Differential Revision: https://phabricator.services.mozilla.com/D247825
2025-05-08 08:05:51 +00:00

186 lines
6.7 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef mozilla_ipc_DataPipe_h
#define mozilla_ipc_DataPipe_h
#include "mozilla/ipc/SharedMemoryHandle.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/ipc/NodeController.h"
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsISupports.h"
#include <memory>
namespace mozilla {
namespace ipc {
namespace data_pipe_detail {
class DataPipeAutoLock;
class DataPipeLink;
class DataPipeBase {
public:
DataPipeBase(const DataPipeBase&) = delete;
DataPipeBase& operator=(const DataPipeBase&) = delete;
protected:
explicit DataPipeBase(bool aReceiverSide, nsresult aError);
DataPipeBase(bool aReceiverSide, ScopedPort aPort,
MutableSharedMemoryHandle&& aShmemHandle,
const std::shared_ptr<SharedMemoryMapping>& aShmem,
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
uint32_t aAvailable);
void CloseInternal(DataPipeAutoLock&, nsresult aStatus) MOZ_REQUIRES(*mMutex);
void AsyncWaitInternal(already_AddRefed<nsIRunnable> aCallback,
already_AddRefed<nsIEventTarget> aTarget,
bool aClosureOnly) MOZ_EXCLUDES(*mMutex);
// Like `nsWriteSegmentFun` or `nsReadSegmentFun`.
using ProcessSegmentFun =
FunctionRef<nsresult(Span<char> aSpan, uint32_t aProcessedThisCall,
uint32_t* aProcessedCount)>;
nsresult ProcessSegmentsInternal(uint32_t aCount,
ProcessSegmentFun aProcessSegment,
uint32_t* aProcessedCount)
MOZ_EXCLUDES(*mMutex);
nsresult CheckStatus(DataPipeAutoLock&) MOZ_REQUIRES(*mMutex);
nsCString Describe(DataPipeAutoLock&) MOZ_REQUIRES(*mMutex);
// Thread safety helper to tell the analysis that `mLink->mMutex` is held when
// `mMutex` is held.
void AssertSameMutex(const std::shared_ptr<Mutex>& aMutex)
MOZ_REQUIRES(*mMutex) MOZ_ASSERT_CAPABILITY(*aMutex) {
MOZ_ASSERT(mMutex == aMutex);
}
virtual ~DataPipeBase();
const std::shared_ptr<Mutex> mMutex;
nsresult mStatus MOZ_GUARDED_BY(*mMutex) = NS_OK;
RefPtr<DataPipeLink> mLink MOZ_GUARDED_BY(*mMutex);
};
template <typename T>
void DataPipeWrite(IPC::MessageWriter* aWriter, T* aParam);
template <typename T>
bool DataPipeRead(IPC::MessageReader* aReader, RefPtr<T>* aResult);
} // namespace data_pipe_detail
class DataPipeSender;
class DataPipeReceiver;
#define NS_DATAPIPESENDER_IID \
{0x6698ed77, 0x9fff, 0x425d, {0xb0, 0xa6, 0x1d, 0x30, 0x66, 0xee, 0xb8, 0x16}}
// Helper class for streaming data to another process.
class DataPipeSender final : public nsIAsyncOutputStream,
public data_pipe_detail::DataPipeBase {
public:
NS_INLINE_DECL_STATIC_IID(NS_DATAPIPESENDER_IID)
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOUTPUTSTREAM
NS_DECL_NSIASYNCOUTPUTSTREAM
private:
friend nsresult NewDataPipe(uint32_t, DataPipeSender**, DataPipeReceiver**);
friend void data_pipe_detail::DataPipeWrite<DataPipeSender>(
IPC::MessageWriter* aWriter, DataPipeSender* aParam);
friend bool data_pipe_detail::DataPipeRead<DataPipeSender>(
IPC::MessageReader* aReader, RefPtr<DataPipeSender>* aResult);
explicit DataPipeSender(nsresult aError)
: data_pipe_detail::DataPipeBase(/* aReceiverSide */ false, aError) {}
DataPipeSender(ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle,
const std::shared_ptr<SharedMemoryMapping>& aShmem,
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
uint32_t aAvailable)
: data_pipe_detail::DataPipeBase(
/* aReceiverSide */ false, std::move(aPort),
std::move(aShmemHandle), aShmem, aCapacity, aPeerStatus, aOffset,
aAvailable) {}
~DataPipeSender() = default;
};
#define NS_DATAPIPERECEIVER_IID \
{0x0a185f83, 0x499e, 0x450c, {0x95, 0x82, 0x27, 0x67, 0xad, 0x6d, 0x64, 0xb5}}
// Helper class for streaming data from another process.
class DataPipeReceiver final : public nsIAsyncInputStream,
public nsIIPCSerializableInputStream,
public data_pipe_detail::DataPipeBase {
public:
NS_INLINE_DECL_STATIC_IID(NS_DATAPIPERECEIVER_IID)
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
private:
friend nsresult NewDataPipe(uint32_t, DataPipeSender**, DataPipeReceiver**);
friend void data_pipe_detail::DataPipeWrite<DataPipeReceiver>(
IPC::MessageWriter* aWriter, DataPipeReceiver* aParam);
friend bool data_pipe_detail::DataPipeRead<DataPipeReceiver>(
IPC::MessageReader* aReader, RefPtr<DataPipeReceiver>* aResult);
explicit DataPipeReceiver(nsresult aError)
: data_pipe_detail::DataPipeBase(/* aReceiverSide */ true, aError) {}
DataPipeReceiver(ScopedPort aPort, MutableSharedMemoryHandle&& aShmemHandle,
const std::shared_ptr<SharedMemoryMapping>& aShmem,
uint32_t aCapacity, nsresult aPeerStatus, uint32_t aOffset,
uint32_t aAvailable)
: data_pipe_detail::DataPipeBase(
/* aReceiverSide */ true, std::move(aPort), std::move(aShmemHandle),
aShmem, aCapacity, aPeerStatus, aOffset, aAvailable) {}
~DataPipeReceiver() = default;
};
constexpr uint32_t kDefaultDataPipeCapacity = 64 * 1024;
/**
* Create a new DataPipe pair. The sender and receiver ends of the pipe may be
* used to transfer data between processes. |aCapacity| is the capacity of the
* underlying ring buffer. If `0` is passed, `kDefaultDataPipeCapacity` will be
* used.
*/
nsresult NewDataPipe(uint32_t aCapacity, DataPipeSender** aSender,
DataPipeReceiver** aReceiver);
} // namespace ipc
} // namespace mozilla
namespace IPC {
template <>
struct ParamTraits<mozilla::ipc::DataPipeSender*> {
static void Write(MessageWriter* aWriter,
mozilla::ipc::DataPipeSender* aParam);
static bool Read(MessageReader* aReader,
RefPtr<mozilla::ipc::DataPipeSender>* aResult);
};
template <>
struct ParamTraits<mozilla::ipc::DataPipeReceiver*> {
static void Write(MessageWriter* aWriter,
mozilla::ipc::DataPipeReceiver* aParam);
static bool Read(MessageReader* aReader,
RefPtr<mozilla::ipc::DataPipeReceiver>* aResult);
};
} // namespace IPC
#endif // mozilla_ipc_DataPipe_h