summaryrefslogtreecommitdiffstats
path: root/mojo/system/raw_channel.h
blob: 3ca677aab1ca6679011929ca76bc3b308d036481 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Copyright 2013 The Chromium 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 MOJO_SYSTEM_RAW_CHANNEL_H_
#define MOJO_SYSTEM_RAW_CHANNEL_H_

#include <vector>

#include "base/basictypes.h"
#include "mojo/system/constants.h"
#include "mojo/system/embedder/scoped_platform_handle.h"
#include "mojo/system/system_impl_export.h"

namespace base {
class MessageLoop;
}

namespace mojo {
namespace system {

class MessageInTransit;

// |RawChannel| is an interface to objects that wrap an OS "pipe". It presents
// the following interface to users:
//  - Receives and dispatches messages on a thread (running a |MessageLoop|; it
//    must be a |MessageLoopForIO| in the case of the POSIX libevent
//    implementation).
//  - Provides a thread-safe way of writing messages (|WriteMessage()|);
//    writing/queueing messages will not block and is atomic from the point of
//    view of the caller. If necessary, messages are queued (to be written on
//    the aforementioned thread).
//
// OS-specific implementation subclasses are to be instantiated using the
// |Create()| static factory method.
//
// With the exception of |WriteMessage()|, this class is thread-unsafe (and in
// general its methods should only be used on the I/O thread).
class MOJO_SYSTEM_IMPL_EXPORT RawChannel {
 public:
  virtual ~RawChannel() {}

  // The |Delegate| is only accessed on the same thread as the message loop
  // (passed in on creation).
  class MOJO_SYSTEM_IMPL_EXPORT Delegate {
   public:
    enum FatalError {
      FATAL_ERROR_UNKNOWN = 0,
      FATAL_ERROR_FAILED_READ,
      FATAL_ERROR_FAILED_WRITE
    };

    // Called when a message is read. This may call |Shutdown()| on the
    // |RawChannel|, but must not destroy it.
    virtual void OnReadMessage(const MessageInTransit& message) = 0;

    // Called when there's a fatal error, which leads to the channel no longer
    // being viable.
    // For each raw channel, at most one |FATAL_ERROR_FAILED_READ| and one
    // |FATAL_ERROR_FAILED_WRITE| notification will be issued. (And it is
    // possible to get both.)
    // After |OnFatalError(FATAL_ERROR_FAILED_READ)| there won't be further
    // |OnReadMessage()| calls.
    virtual void OnFatalError(FatalError fatal_error) = 0;

   protected:
    virtual ~Delegate() {}
  };

  // Static factory method. |handle| should be a handle to a
  // (platform-appropriate) bidirectional communication channel (e.g., a socket
  // on POSIX, a named pipe on Windows). Does *not* take ownership of |delegate|
  // and |message_loop|, which must remain alive while this object does.
  static RawChannel* Create(embedder::ScopedPlatformHandle handle,
                            Delegate* delegate,
                            base::MessageLoop* message_loop);

  // This must be called (on the I/O thread) before this object is used. Returns
  // true on success. On failure, |Shutdown()| should *not* be called.
  virtual bool Init() = 0;

  // This must be called (on the I/O thread) before this object is destroyed.
  virtual void Shutdown() = 0;

  // This is thread-safe. It takes ownership of |message| (always, even on
  // failure). Returns true on success.
  virtual bool WriteMessage(MessageInTransit* message) = 0;

 protected:
  RawChannel(Delegate* delegate, base::MessageLoop* message_loop)
      : delegate_(delegate), message_loop_(message_loop) {}

  Delegate* delegate() { return delegate_; }
  base::MessageLoop* message_loop() { return message_loop_; }

 private:
  Delegate* const delegate_;
  base::MessageLoop* const message_loop_;

  DISALLOW_COPY_AND_ASSIGN(RawChannel);
};

}  // namespace system
}  // namespace mojo

#endif  // MOJO_SYSTEM_RAW_CHANNEL_H_