Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
7d7e20fd
Commit
7d7e20fd
authored
Nov 18, 2015
by
Florian Loitsch
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #405 from floitschG/scheduler
Add a task scheduler.
parents
0760c8be
371bf37d
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
242 additions
and
0 deletions
+242
-0
scheduler.dart
packages/flutter/lib/src/scheduler/scheduler.dart
+152
-0
task.dart
packages/flutter/lib/task.dart
+12
-0
pubspec.yaml
packages/flutter/pubspec.yaml
+1
-0
scheduler_test.dart
packages/unit/test/scheduler/scheduler_test.dart
+77
-0
No files found.
packages/flutter/lib/src/scheduler/scheduler.dart
0 → 100644
View file @
7d7e20fd
// Copyright 2015 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.
import
'dart:async'
;
import
'dart:ui'
show
VoidCallback
;
import
'package:collection/priority_queue.dart'
;
import
'package:flutter/animation.dart'
as
animation
show
scheduler
;
/// An entry in the scheduler's priority queue.
///
/// Combines the task and its priority.
class
_SchedulerEntry
{
final
VoidCallback
task
;
final
int
priority
;
const
_SchedulerEntry
(
this
.
task
,
this
.
priority
);
}
class
Priority
{
static
const
Priority
idle
=
const
Priority
.
_
(
0
);
static
const
Priority
animation
=
const
Priority
.
_
(
100000
);
static
const
Priority
touch
=
const
Priority
.
_
(
200000
);
/// Relative priorities are clamped by this offset.
///
/// It is still possible to have priorities that are offset by more than this
/// amount by repeatedly taking relative offsets, but that's generally
/// discouraged.
static
const
int
kMaxOffset
=
10000
;
const
Priority
.
_
(
this
.
_value
);
int
get
value
=>
_value
;
final
int
_value
;
/// Returns a priority relative to this priority.
///
/// A positive [offset] indicates a higher priority.
///
/// The parameter [offset] is clamped to +/-[kMaxOffset].
Priority
operator
+(
int
offset
)
{
if
(
offset
.
abs
()
>
kMaxOffset
)
{
// Clamp the input offset.
offset
=
kMaxOffset
*
offset
.
sign
;
}
return
new
Priority
.
_
(
_value
+
offset
);
}
/// Returns a priority relative to this priority.
///
/// A positive offset indicates a lower priority.
///
/// The parameter [offset] is clamped to +/-[kMaxOffset].
Priority
operator
-(
int
offset
)
=>
this
+
(-
offset
);
}
/// Scheduler running tasks with specific priorities.
///
/// Combines the task's priority with remaining time in a frame to decide when
/// the task should be run.
///
/// Tasks always run in the idle time after a frame has been committed.
class
TaskScheduler
{
TaskScheduler
.
_
();
SchedulingStrategy
schedulingStrategy
=
new
DefaultSchedulingStrategy
();
final
PriorityQueue
_queue
=
new
HeapPriorityQueue
<
_SchedulerEntry
>(
(
_SchedulerEntry
e1
,
_SchedulerEntry
e2
)
{
// Note that we inverse the priority.
return
-
e1
.
priority
.
compareTo
(
e2
.
priority
);
}
);
/// Wether this scheduler already requested to be woken up as soon as
/// possible.
bool
_wakingNow
=
false
;
/// Wether this scheduler already requested to be woken up in the next frame.
bool
_wakingNextFrame
=
false
;
/// Schedules the given [task] with the given [priority].
void
schedule
(
VoidCallback
task
,
Priority
priority
)
{
bool
isFirstTask
=
_queue
.
isEmpty
;
_queue
.
add
(
new
_SchedulerEntry
(
task
,
priority
.
_value
));
if
(
isFirstTask
)
_wakeNow
();
}
/// Invoked by the system when there is time to run tasks.
void
tick
()
{
if
(
_queue
.
isEmpty
)
return
;
_SchedulerEntry
entry
=
_queue
.
first
;
if
(
schedulingStrategy
.
shouldRunTaskWithPriority
(
entry
.
priority
))
{
try
{
(
_queue
.
removeFirst
().
task
)();
}
finally
{
if
(
_queue
.
isNotEmpty
)
_wakeNow
();
}
}
else
{
_wakeNextFrame
();
}
}
/// Tells the system that the scheduler is awake and should be called as
/// soon a there is time.
void
_wakeNow
()
{
if
(
_wakingNow
)
return
;
_wakingNow
=
true
;
Timer
.
run
(()
{
_wakingNow
=
false
;
tick
();
});
}
/// Tells the system that the scheduler needs to run again (ideally next
/// frame).
void
_wakeNextFrame
()
{
if
(
_wakingNextFrame
)
return
;
_wakingNextFrame
=
true
;
animation
.
scheduler
.
requestAnimationFrame
((
_
)
{
_wakingNextFrame
=
false
;
// RequestAnimationFrame calls back at the beginning of a frame. We want
// to run in the idle-phase of an animation. We therefore request to be
// woken up as soon as possible.
_wakeNow
();
});
}
}
final
TaskScheduler
tasks
=
new
TaskScheduler
.
_
();
abstract
class
SchedulingStrategy
{
bool
shouldRunTaskWithPriority
(
int
priority
);
}
class
DefaultSchedulingStrategy
implements
SchedulingStrategy
{
// TODO(floitsch): for now we only expose the priority. It might be
// interesting to provide more info (like, how long the task ran the last
// time).
bool
shouldRunTaskWithPriority
(
int
priority
)
{
if
(
animation
.
scheduler
.
transientCallbackCount
>
0
)
return
priority
>=
Priority
.
animation
.
_value
;
return
true
;
}
}
packages/flutter/lib/task.dart
0 → 100644
View file @
7d7e20fd
// Copyright 2015 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.
/// The Flutter Task library.
///
/// This library provides means to schedule tasks at given priorities.
/// The library will make sure that tasks are only run when appropriate.
/// For example, an idle-task will not run when an animation is running.
library
task
;
export
'src/scheduler/scheduler.dart'
;
packages/flutter/pubspec.yaml
View file @
7d7e20fd
...
...
@@ -4,6 +4,7 @@ author: Flutter Authors <flutter-dev@googlegroups.com>
description
:
A framework for writing Flutter applications
homepage
:
http://flutter.io
dependencies
:
collection
:
'
>=1.1.3
<2.0.0'
intl
:
'
>=0.12.4+2
<0.13.0'
material_design_icons
:
'
>=0.0.3
<0.1.0'
sky_engine
:
0.0.57
...
...
packages/unit/test/scheduler/scheduler_test.dart
0 → 100644
View file @
7d7e20fd
// Copyright 2015 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.
import
'package:flutter/task.dart'
;
import
'package:test/test.dart'
;
class
TestStrategy
implements
SchedulingStrategy
{
int
allowedPriority
=
10000
;
bool
shouldRunTaskWithPriority
(
int
priority
)
{
return
priority
>=
allowedPriority
;
}
}
void
main
(
)
{
test
(
"Tasks are executed in the right order"
,
()
{
var
strategy
=
new
TestStrategy
();
tasks
.
schedulingStrategy
=
strategy
;
List
input
=
[
2
,
23
,
23
,
11
,
0
,
80
,
3
];
List
executedTasks
=
[];
void
scheduleAddingTask
(
int
x
)
{
tasks
.
schedule
(()
{
executedTasks
.
add
(
x
);
},
Priority
.
idle
+
x
);
}
for
(
int
x
in
input
)
{
scheduleAddingTask
(
x
);
}
strategy
.
allowedPriority
=
100
;
for
(
int
i
=
0
;
i
<
3
;
i
++)
tasks
.
tick
();
expect
(
executedTasks
.
isEmpty
,
isTrue
);
strategy
.
allowedPriority
=
50
;
for
(
int
i
=
0
;
i
<
3
;
i
++)
tasks
.
tick
();
expect
(
executedTasks
.
length
,
equals
(
1
));
expect
(
executedTasks
.
single
,
equals
(
80
));
executedTasks
.
clear
();
strategy
.
allowedPriority
=
20
;
for
(
int
i
=
0
;
i
<
3
;
i
++)
tasks
.
tick
();
expect
(
executedTasks
.
length
,
equals
(
2
));
expect
(
executedTasks
[
0
],
equals
(
23
));
expect
(
executedTasks
[
1
],
equals
(
23
));
executedTasks
.
clear
();
scheduleAddingTask
(
99
);
scheduleAddingTask
(
19
);
scheduleAddingTask
(
5
);
scheduleAddingTask
(
97
);
for
(
int
i
=
0
;
i
<
3
;
i
++)
tasks
.
tick
();
expect
(
executedTasks
.
length
,
equals
(
2
));
expect
(
executedTasks
[
0
],
equals
(
99
));
expect
(
executedTasks
[
1
],
equals
(
97
));
executedTasks
.
clear
();
strategy
.
allowedPriority
=
10
;
for
(
int
i
=
0
;
i
<
3
;
i
++)
tasks
.
tick
();
expect
(
executedTasks
.
length
,
equals
(
2
));
expect
(
executedTasks
[
0
],
equals
(
19
));
expect
(
executedTasks
[
1
],
equals
(
11
));
executedTasks
.
clear
();
strategy
.
allowedPriority
=
1
;
for
(
int
i
=
0
;
i
<
4
;
i
++)
tasks
.
tick
();
expect
(
executedTasks
.
length
,
equals
(
3
));
expect
(
executedTasks
[
0
],
equals
(
5
));
expect
(
executedTasks
[
1
],
equals
(
3
));
expect
(
executedTasks
[
2
],
equals
(
2
));
executedTasks
.
clear
();
strategy
.
allowedPriority
=
0
;
tasks
.
tick
();
expect
(
executedTasks
.
length
,
equals
(
1
));
expect
(
executedTasks
[
0
],
equals
(
0
));
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment