summaryrefslogtreecommitdiff
path: root/include/libcamera/internal/pipeline_handler.h
blob: 75fc63efa3d0da53582e0e1c00b5a0684bf28b44 (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2018, Google Inc.
 *
 * Pipeline handler infrastructure
 */

#pragma once

#include <memory>
#include <queue>
#include <set>
#include <string>
#include <sys/types.h>
#include <vector>

#include <libcamera/base/mutex.h>
#include <libcamera/base/object.h>s="hl com"> */

#include <chrono>
#include <iostream>
#include <string.h>
#include <unistd.h>

#include <libcamera/event_notifier.h>
#include <libcamera/timer.h>

#include "test.h"
#include "thread.h"

using namespace std;
using namespace libcamera;

class EventHandler : public Object
{
public:
	EventHandler()
		: notified_(false)
	{
		int ret = pipe(pipefd_);
		if (ret < 0) {
			ret = errno;
			cout << "pipe() failed: " << strerror(ret) << endl;
		}

		notifier_ = new EventNotifier(pipefd_[0], EventNotifier::Read, this);
		notifier_->activated.connect(this, &EventHandler::readReady);
	}

	~EventHandler()
	{
		delete notifier_;

		close(pipefd_[0]);
		close(pipefd_[1]);
	}

	int notify()
	{
		std::string data("H2G2");
		ssize_t ret;

		memset(data_, 0, sizeof(data_));
		size_ = 0;

		ret = write(pipefd_[1], data.data(), data.size());
		if (ret < 0) {
			cout << "Pipe write failed" << endl;
			return TestFail;
		}

		return TestPass;
	}

	bool notified() const
	{
		return notified_;
	}

private:
	void readReady(EventNotifier *notifier)
	{
		size_ = read(notifier->fd(), data_, sizeof(data_));
		notified_ = true;
	}

	EventNotifier *notifier_;

	int pipefd_[2];

	bool notified_;
	char data_[16];
	ssize_t size_;
};

class EventThreadTest : public Test
{
protected:
	int run()
	{
		Thread thread;
		thread.start();

		/*
		 * Fire the event notifier and then move the notifier to a
		 * different thread. The notifier will not notice the event
		 * immediately as there is no event dispatcher loop running in
		 * the main thread. This tests that a notifier being moved to a
		 * different thread will correctly process already pending
		 * events in the new thread.
		 */
		EventHandler handler;
		handler.notify();
		handler.moveToThread(&thread);

		this_thread::sleep_for(chrono::milliseconds(100));

		/* Must stop thread before destroying the handler. */
		thread.exit(0);
		thread.wait();

		if (!handler.notified()) {
			cout << "Thread event handling test failed" << endl;
			return TestFail;
		}

		return TestPass;
	}
};

TEST_REGISTER(EventThreadTest)