1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <sys/epoll.h>
20 
21 #include <memory>
22 #include <optional>
23 #include <set>
24 #include <shared_mutex>
25 
26 #include "common/libs/fs/shared_fd.h"
27 #include "common/libs/utils/result.h"
28 
29 namespace cuttlefish {
30 
31 struct EpollEvent {
32   SharedFD fd;
33   uint32_t events;
34 };
35 
36 class Epoll {
37  public:
38   static Result<Epoll> Create();
39   Epoll(); // Invalid instance
40   Epoll(Epoll&&);
41   Epoll& operator=(Epoll&&);
42 
43   Result<void> Add(SharedFD fd, uint32_t events);
44   Result<void> Modify(SharedFD fd, uint32_t events);
45   Result<void> AddOrModify(SharedFD fd, uint32_t events);
46   Result<void> Delete(SharedFD fd);
47   Result<std::optional<EpollEvent>> Wait();
48 
49  private:
50   Epoll(SharedFD);
51 
52   /**
53    * This read-write mutex is read-locked to perform epoll operations, and
54    * write-locked to replace the file descriptor.
55    *
56    * A read-write mutex is used here to make it possible to update the watched
57    * set while the epoll resource is being waited on by another thread, while
58    * excluding the possibility of the move constructor or assignment constructor
59    * from stealing the file descriptor out from under waiting threads.
60    */
61   std::shared_mutex epoll_mutex_;
62   SharedFD epoll_fd_;
63   /**
64    * This read-write mutex is read-locked when interacting with it as a const
65    * std::set, and write-locked when interacting with it as a std::set.
66    */
67   std::shared_mutex watched_mutex_;
68   std::set<SharedFD> watched_;
69 };
70 
71 }  // namespace cuttlefish
72