Identifying, authenticating, and authorizing users is a common part of
almost every web application. In CakePHP AuthComponent provides a
pluggable way to do these tasks. AuthComponent allows you to combine
authentication objects and authorization objects to create flexible
ways of identifying and checking user authorization.
Authentication
Authentication is the process of identifying users by provided
credentials and ensuring that users are who they say they are.
Generally, this is done through a username and password, that are checked
against a known list of users. In CakePHP, there are several built-in
ways of authenticating users stored in your application.
FormAuthenticate
allows you to authenticate users based on form POST
data. Usually, this is a login form that users enter information into.
BasicAuthenticate
allows you to authenticate users using Basic HTTP
authentication.
DigestAuthenticate
allows you to authenticate users using Digest
HTTP authentication.
By default AuthComponent
uses FormAuthenticate
.
Choosing an Authentication Type
Generally, you’ll want to offer form based authentication. It is the easiest for
users using a web-browser to use. If you are building an API or webservice, you
may want to consider basic authentication or digest authentication. The key
differences between digest and basic authentication are mostly related to how
passwords are handled. In basic authentication, the username and password are
transmitted as plain-text to the server. This makes basic authentication
un-suitable for applications without SSL, as you would end up exposing sensitive
passwords. Digest authentication uses a digest hash of the username, password,
and a few other details. This makes digest authentication more appropriate for
applications without SSL encryption.
You can also use authentication systems like OpenID as well; however, OpenID is
not part of CakePHP core.
Configuring Authentication Handlers
You configure authentication handlers using the authenticate
config.
You can configure one or many handlers for authentication. Using
multiple handlers allows you to support different ways of logging users
in. When logging users in, authentication handlers are checked in the
order they are declared. Once one handler is able to identify the user,
no other handlers will be checked. Conversely, you can halt all
authentication by throwing an exception. You will need to catch any
thrown exceptions and handle them as needed.
You can configure authentication handlers in your controller’s
beforeFilter()
or initialize()
methods. You can pass
configuration information into each authentication object using an
array:
// Simple setup
$this->Auth->config('authenticate', ['Form']);
// Pass settings in
$this->Auth->config('authenticate', [
'Basic' => ['userModel' => 'Members'],
'Form' => ['userModel' => 'Members']
]);
In the second example, you’ll notice that we had to declare the
userModel
key twice. To help you keep your code DRY, you can use the
all
key. This special key allows you to set settings that are passed
to every attached object. The all key is also exposed as
AuthComponent::ALL
:
// Pass settings in using 'all'
$this->Auth->config('authenticate', [
AuthComponent::ALL => ['userModel' => 'Members'],
'Basic',
'Form'
]);
In the above example, both Form
and Basic
will get the settings
defined for the ‘all’ key. Any settings passed to a specific
authentication object will override the matching key in the ‘all’ key.
The core authentication objects support the following configuration
keys.
fields
The fields to use to identify a user by. You can use keys
username
and password
to specify your username and password fields
respectively.
userModel
The model name of the users table; defaults to Users.
finder
The finder method to use to fetch a user record. Defaults to ‘all’.
passwordHasher
Password hasher class; Defaults to Default
.
- The
scope
and contain
options have been deprecated as of 3.1. Use
a custom finder instead to modify the query to fetch a user record.
- The
userFields
option has been deprecated as of 3.1. Use select()
in
your custom finder.
To configure different fields for user in your initialize()
method:
public function initialize()
{
parent::initialize();
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => ['username' => 'email', 'password' => 'passwd']
]
]
]);
}
Do not put other Auth
configuration keys, such as authError
, loginAction
, etc.,
within the authenticate
or Form
element. They should be at the same level as
the authenticate key. The setup above with other Auth configuration
should look like:
public function initialize()
{
parent::initialize();
$this->loadComponent('Auth', [
'loginAction' => [
'controller' => 'Users',
'action' => 'login',
'plugin' => 'Users'
],
'authError' => 'Did you really think you are allowed to see that?',
'authenticate' => [
'Form' => [
'fields' => ['username' => 'email']
]
],
'storage' => 'Session'
]);
}
In addition to the common configuration, Basic authentication supports
the following keys:
realm
The realm being authenticated. Defaults to env('SERVER_NAME')
.
In addition to the common configuration Digest authentication supports
the following keys:
realm
The realm authentication is for. Defaults to the servername.
nonce
A nonce used for authentication. Defaults to uniqid()
.
qop
Defaults to auth; no other values are supported at this time.
opaque
A string that must be returned unchanged by clients. Defaults
to md5($config['realm'])
.
Note
To find the user record, the database is queried only using the username.
The password check is done in PHP. This is necessary because hashing
algorithms like bcrypt (which is used by default) generate a new hash
each time, even for the same string and you can’t just do simple string
comparison in SQL to check if the password matches.
Customizing Find Query
You can customize the query used to fetch the user record using the finder
option in authenticate class config:
public function initialize()
{
parent::initialize();
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'finder' => 'auth'
]
],
]);
}
This will require your UsersTable
to have finder method findAuth()
.
In the example shown below the query is modified to fetch only required fields
and add a condition. You must ensure that you select the fields you need to
authenticate a user, such as username
and password
:
public function findAuth(\Cake\ORM\Query $query, array $options)
{
$query
->select(['id', 'username', 'password'])
->where(['Users.active' => 1]);
return $query;
}
Note
finder
option is available since 3.1. Prior to that you can use scope
and contain
options to modify a query.
Identifying Users and Logging Them In
-
AuthComponent::
identify
()
You need to manually call $this->Auth->identify()
to identify the user using
credentials provided in request. Then use $this->Auth->setUser()
to log the user in, i.e., save user info to session.
When authenticating users, attached authentication objects are checked
in the order they are attached. Once one of the objects can identify
the user, no other objects are checked. A sample login function for
working with a login form could look like:
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
} else {
$this->Flash->error(__('Username or password is incorrect'));
}
}
}
The above code will attempt to first identify a user by using the POST data.
If successful we set the user info to the session so that it persists across requests
and then redirect to either the last page they were visiting or a URL specified in the
loginRedirect
config. If the login is unsuccessful, a flash message is set.
Warning
$this->Auth->setUser($data)
will log the user in with whatever data is
passed to the method. It won’t actually check the credentials against an
authentication class.
Redirecting Users After Login
-
AuthComponent::
redirectUrl
()
After logging a user in, you’ll generally want to redirect them back to where
they came from. Pass a URL in to set the destination a user should be redirected
to after logging in.
If no parameter is passed, the returned URL will use the following rules:
- Returns the normalized URL from the
redirect
query string value if it is
present and for the same domain the current app is running on. Before 3.4.0,
the Auth.redirect
session value was used.
- If there is no query string/session value and there is a config
loginRedirect
, the loginRedirect
value is returned.
- If there is no redirect value and no
loginRedirect
, /
is returned.
Creating Stateless Authentication Systems
Basic and digest are stateless authentication schemes and don’t require an
initial POST or a form. If using only basic/digest authenticators you don’t
require a login action in your controller. Stateless authentication will
re-verify the user’s credentials on each request, this creates a small amount of
additional overhead, but allows clients to login without using cookies and
makes AuthComponent more suitable for building APIs.
For stateless authenticators, the storage
config should be set to Memory
so that AuthComponent does not use a session to store user record. You may also
want to set config unauthorizedRedirect
to false
so that AuthComponent
throws a ForbiddenException
instead of the default behavior of redirecting to
referrer.
Authentication objects can implement a getUser()
method that can be used to
support user login systems that don’t rely on cookies. A typical getUser method
looks at the request/environment and uses the information there to confirm the
identity of the user. HTTP Basic authentication for example uses
$_SERVER['PHP_AUTH_USER']
and $_SERVER['PHP_AUTH_PW']
for the username
and password fields.
Note
In case authentication does not work like expected, check if queries
are executed at all (see BaseAuthenticate::_query($username)
).
In case no queries are executed check if $_SERVER['PHP_AUTH_USER']
and $_SERVER['PHP_AUTH_PW']
do get populated by the webserver.
If you are using Apache with FastCGI-PHP you might need to add this line
to your .htaccess file in webroot:
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
On each request, these values, PHP_AUTH_USER
and PHP_AUTH_PW
, are used to
re-identify the user and ensure they are the valid user. As with authentication
object’s authenticate()
method, the getUser()
method should return
an array of user information on the success or false
on failure.
public function getUser(ServerRequest $request)
{
$username = env('PHP_AUTH_USER');
$pass = env('PHP_AUTH_PW');
if (empty($username) || empty($pass)) {
return false;
}
return $this->_findUser($username, $pass);
}
The above is how you could implement the getUser method for HTTP basic
authentication. The _findUser()
method is part of BaseAuthenticate
and identifies a user based on a username and password.
Using Basic Authentication
Basic authentication allows you to create a stateless authentication that can be
used in intranet applications or for simple API scenarios. Basic authentication
credentials will be rechecked on each request.
Warning
Basic authentication transmits credentials in plain-text. You should use
HTTPS when using Basic authentication.
To use basic authentication, you’ll need to configure AuthComponent:
$this->loadComponent('Auth', [
'authenticate' => [
'Basic' => [
'fields' => ['username' => 'username', 'password' => 'api_key'],
'userModel' => 'Users'
],
],
'storage' => 'Memory',
'unauthorizedRedirect' => false
]);
Here we’re using username + API key as our fields and use the Users model.
Creating API Keys for Basic Authentication
Because basic HTTP sends credentials in plain-text, it is unwise to have users
send their login password. Instead, an opaque API key is generally used. You can
generate these API tokens randomly using libraries from CakePHP:
namespace App\Model\Table;
use Cake\Auth\DefaultPasswordHasher;
use Cake\Utility\Text;
use Cake\Event\Event;
use Cake\ORM\Table;
class UsersTable extends Table
{
public function beforeSave(Event $event)
{
$entity = $event->getData('entity');
if ($entity->isNew()) {
$hasher = new DefaultPasswordHasher();
// Generate an API 'token'
$entity->api_key_plain = sha1(Text::uuid());
// Bcrypt the token so BasicAuthenticate can check
// it during login.
$entity->api_key = $hasher->hash($entity->api_key_plain);
}
return true;
}
}
The above generates a random hash for each user as they are saved. The above
code assumes you have two columns api_key
- to store the hashed API key, and
api_key_plain
- to the plaintext version of the API key, so we can display
it to the user later on. Using a key instead of a password means that even over
plain HTTP, your users can use an opaque token instead of their original
password. It is also wise to include logic allowing API keys to be regenerated
at a user’s request.
Using Digest Authentication
Digest authentication offers an improved security model over basic
authentication, as the user’s credentials are never sent in the request header.
Instead, a hash is sent.
To use digest authentication, you’ll need to configure AuthComponent:
$this->loadComponent('Auth', [
'authenticate' => [
'Digest' => [
'fields' => ['username' => 'username', 'password' => 'digest_hash'],
'userModel' => 'Users'
],
],
'storage' => 'Memory',
'unauthorizedRedirect' => false
]);
Here we’re using username + digest_hash as our fields and use the Users model.
Hashing Passwords For Digest Authentication
Because Digest authentication requires a password hashed in the format
defined by the RFC, in order to correctly hash a password for use with
Digest authentication you should use the special password hashing
function on DigestAuthenticate
. If you are going to be combining
digest authentication with any other authentication strategies, it’s also
recommended that you store the digest password in a separate column,
from the normal password hash:
namespace App\Model\Table;
use Cake\Auth\DigestAuthenticate;
use Cake\Event\Event;
use Cake\ORM\Table;
class UsersTable extends Table
{
public function beforeSave(Event $event)
{
$entity = $event->getData('entity');
// Make a password for digest auth.
$entity->digest_hash = DigestAuthenticate::password(
$entity->username,
$entity->plain_password,
env('SERVER_NAME')
);
return true;
}
}
Passwords for digest authentication need a bit more information than
other password hashes, based on the RFC for digest authentication.
Note
The third parameter of DigestAuthenticate::password() must match the
‘realm’ config value defined when DigestAuthentication was configured
in AuthComponent::$authenticate. This defaults to env('SCRIPT_NAME')
.
You may wish to use a static string if you want consistent hashes in multiple environments.
Creating Custom Authentication Objects
Because authentication objects are pluggable, you can create custom
authentication objects in your application or plugins. If for example,
you wanted to create an OpenID authentication object. In
src/Auth/OpenidAuthenticate.php you could put the following:
namespace App\Auth;
use Cake\Auth\BaseAuthenticate;
use Cake\Http\ServerRequest;
use Cake\Http\Response;
class OpenidAuthenticate extends BaseAuthenticate
{
public function authenticate(ServerRequest $request, Response $response)
{
// Do things for OpenID here.
// Return an array of user if they could authenticate the user,
// return false if not.
}
}
Authentication objects should return false
if they cannot identify the
user and an array of user information if they can. It’s not required
that you extend BaseAuthenticate
, only that your authentication object
implements Cake\Event\EventListenerInterface
. The BaseAuthenticate
class
provides a number of helpful methods that are commonly used. You can
also implement a getUser()
method if your authentication object needs
to support stateless or cookie-less authentication. See the sections on
basic and digest authentication below for more information.
AuthComponent
triggers two events, Auth.afterIdentify
and Auth.logout
,
after a user has been identified and before a user is logged out respectively.
You can set callback functions for these events by returning a mapping array
from implementedEvents()
method of your authenticate class:
public function implementedEvents()
{
return [
'Auth.afterIdentify' => 'afterIdentify',
'Auth.logout' => 'logout'
];
}
Using Custom Authentication Objects
Once you’ve created your custom authentication object, you can use them
by including them in AuthComponents authenticate array:
$this->Auth->config('authenticate', [
'Openid', // app authentication object.
'AuthBag.Openid', // plugin authentication object.
]);
Note
Note that when using simple notation there’s no ‘Authenticate’ word when
initiating the authentication object. Instead, if using namespaces, you’ll
need to set the full namespace of the class, including the ‘Authenticate’ word.
Handling Unauthenticated Requests
When an unauthenticated user tries to access a protected page first the
unauthenticated()
method of the last authenticator in the chain is called.
The authenticate object can handle sending response or redirection by returning
a response object to indicate no further action is necessary. Due to this, the
order in which you specify the authentication provider in authenticate
config matters.
If authenticator returns null, AuthComponent redirects user to the login action.
If it’s an AJAX request and config ajaxLogin
is specified that element
is rendered else a 403 HTTP status code is returned.
Hashing Passwords
You are responsible for hashing the passwords before they are persisted to the
database, the easiest way is to use a setter function in your User entity:
namespace App\Model\Entity;
use Cake\Auth\DefaultPasswordHasher;
use Cake\ORM\Entity;
class User extends Entity
{
// ...
protected function _setPassword($password)
{
if (strlen($password) > 0) {
return (new DefaultPasswordHasher)->hash($password);
}
}
// ...
}
AuthComponent is configured by default to use the DefaultPasswordHasher
when validating user credentials so no additional configuration is required in
order to authenticate users.
DefaultPasswordHasher
uses the bcrypt hashing algorithm internally, which
is one of the stronger password hashing solutions used in the industry. While it
is recommended that you use this password hasher class, the case may be that you
are managing a database of users whose password was hashed differently.
Creating Custom Password Hasher Classes
In order to use a different password hasher, you need to create the class in
src/Auth/LegacyPasswordHasher.php and implement the
hash()
and check()
methods. This class needs to extend the
AbstractPasswordHasher
class:
namespace App\Auth;
use Cake\Auth\AbstractPasswordHasher;
class LegacyPasswordHasher extends AbstractPasswordHasher
{
public function hash($password)
{
return sha1($password);
}
public function check($password, $hashedPassword)
{
return sha1($password) === $hashedPassword;
}
}
Then you are required to configure the AuthComponent to use your own password
hasher:
public function initialize()
{
parent::initialize();
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'passwordHasher' => [
'className' => 'Legacy',
]
]
]
]);
}
Supporting legacy systems is a good idea, but it is even better to keep your
database with the latest security advancements. The following section will
explain how to migrate from one hashing algorithm to CakePHP’s default.
Changing Hashing Algorithms
CakePHP provides a clean way to migrate your users’ passwords from one algorithm
to another, this is achieved through the FallbackPasswordHasher
class.
Assuming you are migrating your app from CakePHP 2.x which uses sha1
password hashes, you
can configure the AuthComponent as follows:
public function initialize()
{
parent::initialize();
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'passwordHasher' => [
'className' => 'Fallback',
'hashers' => [
'Default',
'Weak' => ['hashType' => 'sha1']
]
]
]
]
]);
}
The first name appearing in the hashers
key indicates which of the classes
is the preferred one, but it will fallback to the others in the list if the
check was unsuccessful.
When using the WeakPasswordHasher
you will need to
set the Security.salt
configure the value to ensure passwords are salted.
In order to update old users’ passwords on the fly, you can change the login
function accordingly:
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
if ($this->Auth->authenticationProvider()->needsPasswordRehash()) {
$user = $this->Users->get($this->Auth->user('id'));
$user->password = $this->request->getData('password');
$this->Users->save($user);
}
return $this->redirect($this->Auth->redirectUrl());
}
...
}
}
As you can see we are just setting the plain password again so the setter
function in the entity will hash the password as shown in the previous example and
then save the entity.
Manually Logging Users In
-
AuthComponent::
setUser
(array $user)
Sometimes the need arises where you need to manually log a user in, such
as just after they registered for your application. You can do this by
calling $this->Auth->setUser()
with the user data you want to ‘login’:
public function register()
{
$user = $this->Users->newEntity($this->request->getData());
if ($this->Users->save($user)) {
$this->Auth->setUser($user->toArray());
return $this->redirect([
'controller' => 'Users',
'action' => 'home'
]);
}
}
Warning
Be sure to manually add the new User id to the array passed to the setUser()
method. Otherwise, you won’t have the user id available.
Accessing the Logged In User
-
AuthComponent::
user
($key = null)
Once a user is logged in, you will often need some particular
information about the current user. You can access the currently logged
in user using AuthComponent::user()
:
// From inside a controller or other component.
$this->Auth->user('id');
If the current user is not logged in or the key doesn’t exist, null will
be returned.
Logging Users Out
-
AuthComponent::
logout
()
Eventually, you’ll want a quick way to de-authenticate someone and
redirect them to where they need to go. This method is also useful if
you want to provide a ‘Log me out’ link inside a members’ area of your
application:
public function logout()
{
return $this->redirect($this->Auth->logout());
}
Logging out users that logged in with Digest or Basic auth is difficult
to accomplish for all clients. Most browsers will retain credentials
for the duration they are still open. Some clients can be forced to
logout by sending a 401 status code. Changing the authentication realm
is another solution that works for some clients.
Deciding When to run Authentication
In some cases you may want to use $this->Auth->user()
in the
beforeFilter(Event $event)
method. This is achievable by using the
checkAuthIn
config key. The following changes which event for which initial
authentication checks should be done:
//Set up AuthComponent to authenticate in initialize()
$this->Auth->config('checkAuthIn', 'Controller.initialize');
Default value for checkAuthIn
is 'Controller.startup'
- but by using
'Controller.initialize'
initial authentication is done before beforeFilter()
method.
Authorization
Authorization is the process of ensuring that an
identified/authenticated user is allowed to access the resources they
are requesting. If enabled AuthComponent
can automatically check
authorization handlers and ensure that logged in users are allowed to
access the resources they are requesting. There are several built-in
authorization handlers and you can create custom ones for your
application or as part of a plugin.
ControllerAuthorize
Calls isAuthorized()
on the active controller,
and uses the return of that to authorize a user. This is often the most
simple way to authorize users.
Note
The ActionsAuthorize
& CrudAuthorize
adapter available in CakePHP
2.x have now been moved to a separate plugin cakephp/acl.
Configuring Authorization Handlers
You configure authorization handlers using the authorize
config key.
You can configure one or many handlers for authorization. Using
multiple handlers allows you to support different ways of checking
authorization. When authorization handlers are checked, they will be
called in the order they are declared. Handlers should return false
, if
they are unable to check authorization, or the check has failed.
Handlers should return true
if they were able to check authorization
successfully. Handlers will be called in sequence until one passes. If
all checks fail, the user will be redirected to the page they came from.
Additionally, you can halt all authorization by throwing an exception.
You will need to catch any thrown exceptions and handle them.
You can configure authorization handlers in your controller’s
beforeFilter()
or initialize()
methods. You can pass
configuration information into each authorization object, using an
array:
// Basic setup
$this->Auth->config('authorize', ['Controller']);
// Pass settings in
$this->Auth->config('authorize', [
'Actions' => ['actionPath' => 'controllers/'],
'Controller'
]);
Much like authenticate
, authorize
, helps you
keep your code DRY, by using the all
key. This special key allows you
to set settings that are passed to every attached object. The all
key
is also exposed as AuthComponent::ALL
:
// Pass settings in using 'all'
$this->Auth->config('authorize', [
AuthComponent::ALL => ['actionPath' => 'controllers/'],
'Actions',
'Controller'
]);
In the above example, both the Actions
and Controller
will get the
settings defined for the ‘all’ key. Any settings passed to a specific
authorization object will override the matching key in the ‘all’ key.
If an authenticated user tries to go to a URL he’s not authorized to access,
he’s redirected back to the referrer. If you do not want such redirection
(mostly needed when using stateless authentication adapter) you can set config
option unauthorizedRedirect
to false
. This causes AuthComponent
to throw a ForbiddenException
instead of redirecting.
Creating Custom Authorize Objects
Because authorize objects are pluggable, you can create custom authorize
objects in your application or plugins. If for example, you wanted to
create an LDAP authorize object. In
src/Auth/LdapAuthorize.php you could put the
following:
namespace App\Auth;
use Cake\Auth\BaseAuthorize;
use Cake\Http\ServerRequest;
class LdapAuthorize extends BaseAuthorize
{
public function authorize($user, ServerRequest $request)
{
// Do things for ldap here.
}
}
Authorize objects should return false
if the user is denied access, or
if the object is unable to perform a check. If the object is able to
verify the user’s access, true
should be returned. It’s not required
that you extend BaseAuthorize
, only that your authorize object
implements an authorize()
method. The BaseAuthorize
class provides
a number of helpful methods that are commonly used.
Using Custom Authorize Objects
Once you’ve created your custom authorize object, you can use them by
including them in your AuthComponent’s authorize array:
$this->Auth->config('authorize', [
'Ldap', // app authorize object.
'AuthBag.Combo', // plugin authorize object.
]);
Using No Authorization
If you’d like to not use any of the built-in authorization objects and
want to handle things entirely outside of AuthComponent, you can set
$this->Auth->config('authorize', false);
. By default AuthComponent starts off
with authorize
set to false
. If you don’t use an authorization scheme,
make sure to check authorization yourself in your controller’s
beforeFilter or with another component.
Making Actions Public
-
AuthComponent::
allow
($actions = null)
There are often times controller actions that you wish to remain
entirely public or that don’t require users to be logged in.
AuthComponent is pessimistic and defaults to denying access. You can
mark actions as public actions by using AuthComponent::allow()
. By
marking actions as public, AuthComponent will not check for a logged in
user nor will authorize objects to be checked:
// Allow all actions
$this->Auth->allow();
// Allow only the index action.
$this->Auth->allow('index');
// Allow only the view and index actions.
$this->Auth->allow(['view', 'index']);
By calling it empty you allow all actions to be public.
For a single action, you can provide the action name as a string. Otherwise, use an array.
Note
You should not add the “login” action of your UsersController
to allow list.
Doing so would cause problems with the normal functioning of AuthComponent
.
Making Actions Require Authorization
-
AuthComponent::
deny
($actions = null)
By default all actions require authorization. However, after making actions
public you want to revoke the public access. You can do so using
AuthComponent::deny()
:
// Deny all actions.
$this->Auth->deny();
// Deny one action
$this->Auth->deny('add');
// Deny a group of actions.
$this->Auth->deny(['add', 'edit']);
By calling it empty you deny all actions.
For a single action, you can provide the action name as a string. Otherwise, use an array.
Using ControllerAuthorize
ControllerAuthorize allows you to handle authorization checks in a
controller callback. This is ideal when you have very simple
authorization or you need to use a combination of models and components
to do your authorization and don’t want to create a custom authorize
object.
The callback is always called isAuthorized()
and it should return a
boolean as to whether or not the user is allowed to access resources in
the request. The callback is passed the active user so it can be
checked:
class AppController extends Controller
{
public function initialize()
{
parent::initialize();
$this->loadComponent('Auth', [
'authorize' => 'Controller',
]);
}
public function isAuthorized($user = null)
{
// Any registered user can access public functions
if (!$this->request->getParam('prefix')) {
return true;
}
// Only admins can access admin functions
if ($this->request->getParam('prefix') === 'admin') {
return (bool)($user['role'] === 'admin');
}
// Default deny
return false;
}
}
The above callback would provide a very simple authorization system
where only users with role = admin could access actions that were in
the admin prefix.


General SPARQL query : input query, set any options and press "Get Results"
Target graph URI (or use FROM in the query) If no dataset is provided, the query will execute against an empty one. The query can contain use VALUES to set some variables. Output: JSON XML Text CSV TSV XSLT style sheet (blank for none): Force the accept header to text/plain regardless
FROM
VALUES


Openfire is a powerful instant messaging (IM) and chat server that implements the XMPP protocol. This document will guide you through installing Openfire. For a full list of features and more information, please visit the Openfire website: http://www.igniterealtime.org/projects/openfire/
rpm -ivh openfire_3_0_0.rpm
If using the .tar.gz, extract the archive to /opt or /usr/bin:tar -xzvf openfire_3_0_0.tar.gz
mv openfire /opt
Note: the .tar.gz build does not contain a bundled Java runtime (JRE). Therefore, you must have JDK or JRE 1.5.0 (Java 5) or later installed on your system. You can check your java version by typing "java -version" at the command line and (if necessary) upgrade your Java installation by visiting http://java.sun.com.
To complete the installation of Openfire, you'll need to perform each of the following steps:
This document also includes information on:
The files in your distribution should be as follows (some sub-directories omitted for brevity):
openfire/ |- readme.html |- license.html |- conf/ |- bin/ |- jre/ |- lib/ |- plugins/ |- admin/ |- resources/ |-database/ |-security/ |- documentation/
Openfire can store its data in an embedded database or you can choose to use an external database such as MySQL or Oracle. If you would like to use an external database, you must prepare it before proceeding with installation. View the database setup documentation for more information.
A web-based, "wizard" driven setup and configuration tool is built into Openfire. Simply launch Openfire (platform-specific instructions below) and use a web browser to connect to the admin console. The default port for the web-based admin console is 9090. If you are on the same machine as Openfire, the following URL will usually work: http://<IP_ADDRESS>:9090. Initial setup and administration can also be done from a remote computer using LAN IP address instead or hostname if it is resolvable by the remote computer. Windows Server administrators should add http://<IP_ADDRESS> address to Internet Explorer's Trusted Sites list, if Enhanced Security configuration is enabled in Internet Explorer. Otherwise they will get a blank screen.
After completing the above steps, Openfire will be configured
and you can use the web-based admin console to administer
the server. The URL should be the same as you used to setup the server
unless you changed the port during the setup.
If you used the Openfire installer, a shortcut for starting the a graphical launcher is provided in your Start Menu. Otherwise, run openfire.exe in the bin/ directory of your Openfire installation. A button on the on the launcher allows you to automatically open your web browser to the correct URL to finish setting up the server:
If you're running Openfire on Windows, you will likely want to run Openfire as a standard Windows service after initial setup. If you used the Windows installer, a openfire-service.exe file will be in the bin directory of the installation. You can use this executable to install and control the Openfire service.
From a console window, you can run the following commands:
You can also use the Services tool in the Windows Control Panel to start and stop the service.
Note: the graphical launcher is not compatible with the Windows service at this time. If you install the service, you should use service controls as described above to control the server rather than the graphical launcher.
Advanced users may wish to pass in parameters to the Java virtual machine (VM) to customize the runtime environment of Openfire. You can do this by creating openfire.vmoptions files in the bin/ directory of your Openfire installation. For the Windows service, you'd create a new text file called openfire-service.vmoptions. Each parameter to the VM should be on a new line of the file. For example, to set the minimum heap size to 512 MB and max VM heap size to 1024 MB, you'd use:
-Xms512m -Xmx1024mTo create parameters for the normal launcher, create a file called openfired.vmoptions (since the openfire.exe launcher invokes the openfired.exe executable to actually start the server).
# /etc/init.d/openfire
Usage /etc/init.d/openfire {start|stop|restart|status|condrestart|reload}
# /etc/init.d/openfire start
Starting openfire:
# ./openfire
Usage: ./openfire {start|stop}
# ./openfire start
Starting openfire
Advanced users may wish to pass in parameters to the Java virtual machine (VM) to customize the runtime environment of Openfire. If you installed via RPM, you can customize this by editing /etc/sysconfig/openfire and looking at the OPENFIRE_OPTS option. If you installed via .tar.gz, you will need to tweak your startup script to fit your needs.


DOB NOW JOB FILING: SPRINKLERS
JOB NUMBER:
BIN NUMBER:
WORK TYPE:
PROFESSIONAL CERTIFICATE:
FILING STATUS:
JOB DESCRIPTION:
Filing Date
CPE Assigned Date
CPE Action Date
PE Assigned Date
First Objection Date
Latest Objection Date
Latest Resubmit Date
Plan Approved Date
Permit Issued Date
Permit Signed Off Date


Please exec the test.sh in terminal, there are the page for testing:
1. page for testing scroll
2. page for testing formfill
3. page for testing touch event（mobile only）
click me
bottom button


Have a site already or want to create one from scratch? Upload a .zip file of your site's content and we'll host it for you!


#include <simulator_processor.hpp>
◆ ProcessorBase
◆ SimulatorProcessor()
| SimulatorProcessor::SimulatorProcessor |
( |
| ) |
|
|
inline |
◆ ~SimulatorProcessor()
| SimulatorProcessor::~SimulatorProcessor |
( |
| ) |
|
◆ earlyInitHook()
|
|
inlinestaticnoexceptinherited |
Perform any special initialization steps.
The earlyInitHook_() function must be implemented by the derived class as a static function.
These functions run before the C Run-time setup functions are called, and normal functionality (e.g. OS concepts) are not available.
Early initialization steps represent any super early code that needs to execute. For example, DRAM might need to be initialized before the boot process can relocate memory to its proper location in memory.
These functions are declared static to prevent you from easily using drivers within their confines
◆ earlyInitHook_()
| static void SimulatorProcessor::earlyInitHook_ |
( |
| ) |
|
|
inlinestatic |
◆ init()
Initialize the processor.
The initProcessor_() function must be implemented by the derived class.
Perform any steps necessary for initializing the processor & processor peripheral devices for use.
Note that this is only intended to be processor initialization. Platform initialization nis handled by the init() function.
This function will likely invoke the VirtualProcessor::init() function, but the order and actual initialization process is left to the derived class.
◆ init_()
| void SimulatorProcessor::init_ |
( |
| ) |
|
◆ name()
Returns the Virtual HW Platform's name.
◆ name_cstr()
Returns the platform name as a cstring for C API compatibility.
◆ reset()
Reset the chip.
The reset_() function must be implemnted by the derived class.
A soft reset is intended to reset the program to the beginning without performing a full power cycle.
◆ reset_()
| void SimulatorProcessor::reset_ |
( |
| ) |
|
|
inline |
The documentation for this class was generated from the following files:


Last updated: 2020-05-12
Checks: 7 0
Knit directory: daarem/analysis/
This reproducible R Markdown analysis was created with workflowr (version 1.6.2). The Checks tab describes the reproducibility checks that were applied when the results were created. The Past versions tab lists the development history.
Great! Since the R Markdown file has been committed to the Git repository, you know the exact version of the code that produced these results.
Great job! The global environment was empty. Objects defined in the global environment can affect the analysis in your R Markdown file in unknown ways. For reproduciblity it’s best to always run the code in an empty environment.
The command set.seed(1)
was run prior to running the code in the R Markdown file. Setting a seed ensures that any results that rely on randomness, e.g. subsampling or permutations, are reproducible.
Great job! Recording the operating system, R version, and package versions is critical for reproducibility.
Nice! There were no cached chunks for this analysis, so you can be confident that you successfully produced the results during this run.
Great job! Using relative paths to the files within your workflowr project makes it easier to run your code on other machines.
Great! You are using Git for version control. Tracking code development and connecting the code version to the results is critical for reproducibility.
The results in this page were generated with repository version b16e673. See the Past versions tab to see a history of the changes made to the R Markdown and HTML files.
Note that you need to be careful to ensure that all relevant files for the analysis have been committed to Git prior to generating the results (you can use wflow_publish
or wflow_git_commit
). workflowr only checks the R Markdown file, but you know if there are other scripts or data files that it depends on. Below is the status of the Git repository when the results were generated:
working directory clean
Note that any generated files, e.g. HTML, png, CSS, etc., are not included in this status report because it is ok for generated content to have uncommitted changes.
These are the previous versions of the repository in which changes were made to the R Markdown (analysis/linreg.Rmd
) and HTML (docs/linreg.html
) files. If you’ve configured a remote Git repository (see ?wflow_git_remote
), click on the hyperlinks in the table below to view the files as they were in that past version.
| File | Version | Author | Date | Message |
|---|---|---|---|---|
| html | b58b5db | Peter Carbonetto | 2020-05-12 | Re-built linreg analysis after a couple small changes to the daarem |
| Rmd | 453b627 | Peter Carbonetto | 2020-05-12 | wflow_publish(“linreg.Rmd”) |
| html | 0279af9 | Peter Carbonetto | 2019-06-20 | Revised text in linreg analysis. |
| Rmd | 20a75b6 | Peter Carbonetto | 2019-06-20 | wflow_publish(“linreg.Rmd”) |
| html | a82f29e | Peter Carbonetto | 2019-06-20 | Adjusted fig. dimensions in linreg analysis. |
| Rmd | 98e78d8 | Peter Carbonetto | 2019-06-20 | wflow_publish(“linreg.Rmd”) |
| html | 3a81027 | Peter Carbonetto | 2019-06-20 | Re-ran wflow_publish(“linreg.Rmd”) after (small) changes to mr_ash code. |
| html | 5a7d3a8 | Peter Carbonetto | 2019-06-19 | Fixed Markdown in linreg analysis. |
| Rmd | 869405c | Peter Carbonetto | 2019-06-19 | wflow_publish(“linreg.Rmd”) |
| html | 639fe74 | Peter Carbonetto | 2019-06-19 | Ran wflow_publish(“linreg.Rmd”). |
| Rmd | c08a115 | Peter Carbonetto | 2019-06-19 | Added new results on mr-ash to linreg analysis. |
| Rmd | 6da0688 | Peter Carbonetto | 2019-06-19 | Moved ridge analysis to linreg. |
In this small demonstration, we show how the DAAREM method can be used to accelerate co-ordinate ascent algorithms for linear regression models.
We begin with a simple case in which the regression coefficients are independently and identically drawn from a simple normal prior with zero mean—i.e., ridge regression. The co-ordinate ascent update for \(\hat{\beta}_i\), the estimate of the regression coefficient for variable \(i\), is \[\hat{\beta}_i = \frac{(X^Ty)_i - \sum_{j\,\neq\,i} (X^T\!X)_{ij} \hat{\beta}_j} {(X^T\!X)_{ii} + 1/\sigma_0^2},\] where \(X\) is the \(n \times p\) matrix storing the \(n\) observations of \(p\) variables, \(y\) is the \(n\)-vector of regression outcomes, and the prior on the coefficients is assumed to be i.i.d normal with mean zero and variance \(\sigma^2 \sigma_0^2\), where \(\sigma^2\) is the variance of the residual.
These variables specify how the data are generated: n
is the number of simulated samples, p
is the number of simulated predictors, na
is the number of simulated predictors that have a nonzero effect, se
is the variance of the residual.
n <- 200
p <- 500
na <- 10
se <- 4
This specifies the prior on the regression coefficients: it is normal with zero mean and variance s0
.
s0 <- 1/se
Load some packages and function definitions used in the example below.
library(MASS)
library(daarem)
library(ggplot2)
library(cowplot)
theme_set(theme_cowplot())
source("../code/misc.R")
source("../code/datasim.R")
source("../code/ridge.R")
source("../code/mr_ash.R")
Initialize the sequence of pseudorandom numbers.
set.seed(1)
Simulate predictors with “decaying” correlations.
X <- simulate_predictors_decaying_corr(n,p,s = 0.5)
X <- scale(X,center = TRUE,scale = FALSE)
Generate additive effects for the markers so that exactly na
of them have a nonzero effect on the trait.
i <- sample(p,na)
b <- rep(0,p)
b[i] <- rnorm(na)
Simulate the continuous outcomes, and center them.
y <- drop(X %*% b + sqrt(se)*rnorm(n))
y <- y - mean(y)
Set the initial estimate of the coefficients.
b0 <- rep(0,p)
Fit the ridge regression model by running 100 iterations of the basic co-ordinate ascent updates. Note that the co-ordinate ascent updates are very simple, and are easily implemented in a single line of R code; see the code for the ridge.update
function.
out <- system.time(fit1 <- ridge(X,y,b0,s0,numiter = 100))
f1 <- ridge.objective(X,y,fit1$b,s0)
cat(sprintf("Computation took %0.2f seconds.\n",out["elapsed"]))
cat(sprintf("Objective value at solution is %0.12f.\n",f1))
# Computation took 0.43 seconds.
# Objective value at solution is -22.515798678253.
Fit the ridge regression model again, this time using DAAREM to speed up the co-ordinate ascent algorithm.
out <- system.time(fit2 <- daarridge(X,y,b0,s0,numiter = 100))
f2 <- ridge.objective(X,y,fit2$b,s0)
cat(sprintf("Computation took %0.2f seconds.\n",out["elapsed"]))
cat(sprintf("Objective value at solution is %0.12f.\n",f2))
# Computation took 0.45 seconds.
# Objective value at solution is -22.238771667148.
We see that the DAAREM solution is better (it has a higher posterior value).
Since the ridge estimate as a closed-form solution, we can easily compare the above estimates obtained via co-ordinate ascent against the actual solution.
bhat <- drop(solve(t(X) %*% X + diag(rep(1/s0,p)),t(X) %*% y))
f <- ridge.objective(X,y,bhat,s0)
This plot shows the improvement in the solution over time for the two co-ordinate ascent algorithms: the vertical axis (“distance to best solution”) shows the difference between the largest log-posterior obtained, and the log-posterior at the actual ridge solution (bhat
).
pdat <-
rbind(data.frame(iter = 1:100,dist = f - fit1$value,method = "basic"),
data.frame(iter = 1:100,dist = f - fit2$value,method = "accelerated"))
p <- ggplot(pdat,aes(x = iter,y = dist,col = method)) +
geom_line(size = 1) +
scale_y_continuous(trans = "log10",breaks = 10^seq(-8,4)) +
scale_color_manual(values = c("darkorange","dodgerblue")) +
labs(x = "iteration",y = "distance from solution")
print(p)
From this plot, we see that the accelerated algorithm progresses much more rapidly toward the solution; after 100 iterations, it nearly recovers the actual ridge estimates, whereas the unaccelerated version is still very far away.
Next, we consider a less simple case in which the regression coefficients are independently and identically drawn from mixture of zero-centered normals; this can be seen as a multivariate extension to the adaptive shrinkage model, so we call this “multivariate regression adaptive shrinkage” (mr-ash). Although posterior computations with this model are more difficult than with ridge regression, we can nonetheless obtain simple co-ordinate ascent updates for computing posterior expectations of the coefficients if we introduce a variational approximation to the posterior distribution. The full derivation is omitted here; see the code in the mr_ash_update
function for details. (Note that the co-ordinate ascent updates, unlike the ridge regression updates, are only guaranteed to recover a local maximum of the objective function being optimized.)
These two variables specify the variances and mixture weights for the mixture-of-normals priors. Here we illustrate mr-ash with a prior that is a mixture of three normals.
s0 <- c(0.1,1,10)^2/se
w <- c(0.5,0.25,0.25)
Fit the mr-ash model by running 200 iterations of the basic co-ordinate ascent updates.
out <- system.time(fit3 <- mr_ash(X,y,b0,se,s0,w,numiter = 100))
cat(sprintf("Computation took %0.2f seconds.\n",out["elapsed"]))
# Computation took 1.19 seconds.
Fit the mr-ash model again, this time using DAAREM to speed up the co-ordinate ascent updates.
out <- system.time(fit4 <- daar_mr_ash(X,y,b0,se,s0,w,numiter = 100))
cat(sprintf("Computation took %0.2f seconds.\n",out["elapsed"]))
# Computation took 1.17 seconds.
Like the plot above, this plot shows the improvement in the solution over time for the basic and accelated mr-ash co-ordinate ascent algorithms. Both algorithms end up at the same solution. But the “accelerated” version indeed arrives at the solution much more quickly, whereas the basic algorithm gets “stuck” for many iterations.
f <- max(c(fit3$value,fit4$value)) + 1e-8
pdat <-
rbind(data.frame(iter = 1:100,dist = f - fit3$value,method = "basic"),
data.frame(iter = 1:100,dist = f - fit4$value,method = "accelerated"))
p <- ggplot(pdat,aes(x = iter,y = dist,col = method)) +
geom_line(size = 1) +
scale_y_continuous(trans = "log10",breaks = 10^seq(-8,4)) +
scale_color_manual(values = c("darkorange","dodgerblue")) +
labs(x = "iteration",y = "distance from best solution")
print(p)
sessionInfo()
# R version 3.6.2 (2019-12-12)
# Platform: x86_64-apple-darwin15.6.0 (64-bit)
# Running under: macOS Catalina 10.15.4
#
# Matrix products: default
# BLAS: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRblas.0.dylib
# LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib
#
# locale:
# [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#
# attached base packages:
# [1] stats graphics grDevices utils datasets methods base
#
# other attached packages:
# [1] cowplot_1.0.0 ggplot2_3.3.0 daarem_0.4.1 MASS_7.3-51.4
#
# loaded via a namespace (and not attached):
# [1] Rcpp_1.0.3 compiler_3.6.2 pillar_1.4.3 later_1.0.0
# [5] git2r_0.26.1 workflowr_1.6.2 tools_3.6.2 digest_0.6.23
# [9] evaluate_0.14 lifecycle_0.1.0 tibble_2.1.3 gtable_0.3.0
# [13] pkgconfig_2.0.3 rlang_0.4.5 yaml_2.2.0 xfun_0.11
# [17] withr_2.1.2 stringr_1.4.0 dplyr_0.8.3 knitr_1.26
# [21] fs_1.3.1 rprojroot_1.3-2 grid_3.6.2 tidyselect_0.2.5
# [25] glue_1.3.1 R6_2.4.1 rmarkdown_2.0 farver_2.0.1
# [29] purrr_0.3.3 magrittr_1.5 whisker_0.4 backports_1.1.5
# [33] scales_1.1.0 promises_1.1.0 htmltools_0.4.0 assertthat_0.2.1
# [37] colorspace_1.4-1 httpuv_1.5.2 labeling_0.3 stringi_1.4.3
# [41] munsell_0.5.0 crayon_1.3.4


Overview¶
About¶
impyute is a general purpose, imputations library written in Python. In statistics, imputation is the method of estimating missing values in a data set. There are a lot of different types of imputation, the result of the various types of datasets. On datasets with high percentages of missing values, some methods work better than others and vice versa. Datasets can be cross sectional or time series, linear or non linear, continuous or categorical or boolean. As you can imagine, there are a lot of different specifications that need to be kept in mind.
Functionality¶
impyute was built for convenience, an all in one stop so that users can impute their dataset with minimal knowledge and get on with their day. With that in mind, the following tools are provided for the user:
- Imputations (Fill in missing values)
- Deletions (Only use complete data)
- Diagnostics to identify the skew and distribution of missing values
- Comparison function to experiment with how different machine learning algorithms are affected by different imputation algorithms.
- Dataset generation to experiment with different types of missingness and different types of data.
Formatting your Data¶
Prior to running, checks are run to ensure the given data is in an acceptable format. Please ensure that your data satisfies the following criterion:
- numpy.ndarray with type numpy.float
- Columns are along the x-axis and individual datapoints are along the y-axis.
- 2D Matrix (3D is also allowed in certain cases, but requires special treatment)
- Missing values can be found with numpy.isnan


Tables in a database correspond to Java classes and table columns correspond to properties of those classes. Properties follow JavaBean rules in that there are getter and setter methods for each property. For this reason, object inflated from the database are usually referred to as beans.
Inflated beans are stored in a Map (java.util.Map), where the value is the bean and the key is the primary key. There is one Map for each class of bean (typically one Map for each database table). The implementations of Map support real-time updates. The class hierarchy used is shown below.
An ObservableMap allows listeners to be added, who are notified when the map's content changes. ObservableMaps fire MapEvents which indicate if beans have been added, removed or deleted.
BeanFactory subclasses ObservableMap. Beans can be retrieved using the primary key of the bean or alternatively based on criteria. i.e. you can call:
Object get(Object key) Object[] get(Object[] keys) BeanCollection get(CriterionGroup criteria)
on the BeanFactory. TabularDataBeanFactory subclasses BeanFactory and generates beans from TabularData. SqlBeanFactory subclasses TabularDataBeanFactory and populates itself from a database (by providing an implementation of TabularData that accesses java.sql.ResultSet). The SqlBeanFactory uses select statements to retrieve beans from the database and also listens for changes to data in the database.
Bhavaya allows you to obtain BeanCollections from a BeanFactory (collections of beans) that match certain criteria. The BeanFactory will also ensure that beans are inserted, updated or deleted in the BeanCollection, as data in the database changes, where that data meets the BeanCollection's criteria. BeanCollections are subclasses of Collection (java.util.Collection) extended with real-time functionality. The class hierarchy used is shown below.


Loading...
Loading...
Loading...
Loading...
Do you want soundbytes you send to BurkeBlack's stream to be announced in chat?
| Name | Key |
|---|
| Name | Key |
|---|
| Name | Redeem |
|---|
This Twitch Extension was developed for use exclusively in BurkeBlack's Twitch channel.This extension was developed by swiftyspiffy.


--- layout: post title: Twitter and partial unreliability date: 2008-01-18 00:00:00 categories: digital-media software-development ---
Russ posts about a federated Twitter. Here's an unformed half-thought, partially drawing on our experience with measuring progress in Scrum: maybe it's better in some circumstances for something to be 100% down than 95% available.
Case in point, from the software development angle: it's easy for software, or parts of software, to be 95% done. For about 95% of a project. Getting something to that it's-nearly-there stage is easy, it's completing it (working out those "last few integration problems") that causes all the heartache and pain.
So it is with a messaging system. If 5% of my emails aren't getting delivered, I'm not in a 5% worse situation than 0% of my emails not getting delivered - it's *way* worse than that. Suddenly email is rubbish, because I have to consider that my email might not arrive.
Same with free software: 1p for a download is a radically different price to 0p, because I have to think about paying.
And ditto with a federated messaging service: I'd rather Twitter (which I love but have never paid a bean for) was totally dead, than kind-of-working (maybe delivering my updates to most of my readers, say... or giving me updates from some readers but not others).


Make your way to sace in the comfort of your own rocket, elevator or transporter.
Even if you're traveling tomorrow, you can still get tickets today. We have a number of convenintly located ports around the globe to service everybody.
If you need to get to space today, why not try out a transporter? Dispite the claims, there are have been no deaths in the last 6 weeks!
For cheapest fares, catch the next RocketBus to the stars. Cheaper on your wallet and easiest way to make friends.


This tool is an automatic mailer written in PHP language. Permit to send a great quantity of email in automatic manner
In order to send email is necessary to provide to the tool a CSV file that contain recipients email
No of course, the format of CSV is fixed and unfortunately hardcoded inside the script. Please contact administrator to change the format of CSV. Up to now, CSV must contain 3 columns: NAME, TEL, EMAIL. Below it is shown an example.
NOME;TELEFONO;MAIL BIG CORP<EMAIL_ADDRESS>LITTLE CORP<EMAIL_ADDRESS>| NOME | TELEFONO | |
|---|---|---|
| BIG CORP SNC |<PHONE_NUMBER>1261 |<EMAIL_ADDRESS>|
| LITTLE CORP LTD |<PHONE_NUMBER>1983 |<EMAIL_ADDRESS>|
Please note that all field are mandatory.
You can use shortcode inside the email content. Those listed above are the enabled one:
{company_name} --> Will be substituted with the company name


Apple Music for Business Could Come to a Store Near You
by Andrew OrrApple not only wants to provide music for consumers but also businesses in the form of muzak. So far businesses that play Apple Music in their stores include Levi Strauss & Co. and Harrods (via WSJ—hard paywall).
Apple Music for Business
Apple is partnering with PlayNetwork Inc., which specializes in providing music for commercial use. Apple is the one that will create and suggest playlists to use for businesses. A lot of music licensed for commercial use is more expensive so businesses can potentially save money by switching to Apple Music.
But on opposite side, a report from Nielsen Music last year estimated that artists, labels, and music producers collectively lose US$2.65 billion per year when businesses switch to consumer music services. PlayNetwork says that Apple Music for Business is “priced competitively.” Although it didn’t give a specific price it notes that similar services are being offered around US$25-US$35 per month per store.
Apple Music for Business has been running for six months and so far has 25 accounts. Once these are fully implemented Apple could be servicing over 10,000 stores, including its own retail stores.
Further Reading:
[Tim Cook Talks Steve Jobs, Environment and Privacy at Salesforce Dreamforce]


|
QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.30
|
#include <ql/experimental/exoticoptions/analyticholderextensibleoptionengine.hpp>
Public Member Functions | |
| AnalyticHolderExtensibleOptionEngine (ext::shared_ptr< GeneralizedBlackScholesProcess > process) | |
| void | calculate () const override |
| Public Member Functions inherited from GenericEngine< HolderExtensibleOption::arguments, HolderExtensibleOption::results > | |
| PricingEngine::arguments * | getArguments () const override |
| const PricingEngine::results * | getResults () const override |
| void | reset () override |
| void | update () override |
| Public Member Functions inherited from PricingEngine | |
| ~PricingEngine () override=default | |
| virtual arguments * | getArguments () const =0 |
| virtual const results * | getResults () const =0 |
| virtual void | reset ()=0 |
| virtual void | calculate () const =0 |
| Public Member Functions inherited from Observable | |
| Observable () | |
| Observable (const Observable &) | |
| Observable & | operator= (const Observable &) |
| virtual | ~Observable ()=default |
| void | notifyObservers () |
| Public Member Functions inherited from Observer | |
| Observer ()=default | |
| Observer (const Observer &) | |
| Observer & | operator= (const Observer &) |
| virtual | ~Observer () |
| std::pair< iterator, bool > | registerWith (const ext::shared_ptr< Observable > &) |
| void | registerWithObservables (const ext::shared_ptr< Observer > &) |
| Size | unregisterWith (const ext::shared_ptr< Observable > &) |
| void | unregisterWithAll () |
| virtual void | update ()=0 |
| virtual void | deepUpdate () |
Private Member Functions | |
| Real | strike () const |
| Time | firstExpiryTime () const |
| Time | secondExpiryTime () const |
| Volatility | volatility () const |
| Rate | riskFreeRate () const |
| Rate | dividendYield () const |
| DiscountFactor | dividendDiscount (Time t) const |
| DiscountFactor | riskFreeDiscount (Time t) const |
| Real | I1Call () const |
| Real | I2Call () const |
| Real | I1Put () const |
| Real | I2Put () const |
| BlackScholesCalculator | bsCalculator (Real spot, Option::Type optionType) const |
| Real | M2 (Real a, Real b, Real c, Real d, Real rho) const |
| Real | N2 (Real a, Real b) const |
| Real | y1 (Option::Type) const |
| Real | y2 (Option::Type) const |
| Real | z1 () const |
| Real | z2 () const |
Private Attributes | |
| ext::shared_ptr< GeneralizedBlackScholesProcess > | process_ |
Additional Inherited Members | |
| Public Types inherited from Observer | |
| typedef set_type::iterator | iterator |
| Protected Attributes inherited from GenericEngine< HolderExtensibleOption::arguments, HolderExtensibleOption::results > | |
| HolderExtensibleOption::arguments | arguments_ |
| HolderExtensibleOption::results | results_ |
Definition at line 33 of file analyticholderextensibleoptionengine.hpp.
|
explicit |
Definition at line 32 of file analyticholderextensibleoptionengine.cpp.
|
overridevirtual |
Implements PricingEngine.
Definition at line 38 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 264 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 271 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 275 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 279 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 282 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 286 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 291 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 295 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 95 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 129 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 166 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 196 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 228 of file analyticholderextensibleoptionengine.cpp.
Definition at line 254 of file analyticholderextensibleoptionengine.cpp.
Definition at line 259 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 299 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 310 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 321 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 331 of file analyticholderextensibleoptionengine.cpp.
|
private |
Definition at line 41 of file analyticholderextensibleoptionengine.hpp.


People Directory
Search all or part of a name, email address, or phone number.
| Keywords: | dir, ppl |
| For help: | dir [help] |
| Examples: |
|
Get info on MIT people, shuttles and classes via text message.
Simply text message your request to 649338 (”MITEDU”) and we'll text message back the information you need.
For a list of keywords and tips, text message "help" to 648338 ("MITEDU")
This service is free from MIT, but carrier charges may apply.
To get started, just text “help” to 648338 (“MITEDU”)
Search all or part of a name, email address, or phone number.
| Keywords: | dir, ppl |
| For help: | dir [help] |
| Examples: |
|
Get an up-to-the-minute schedule by shuttle name or two-letter abbreviation.
| Keywords: | bus, shuttle | ||||||||||||||
| For help: | bus [help] | ||||||||||||||
| Examples: |
|
||||||||||||||
| Shuttle route abbreviations: |
|
Get course information and latest announcements by class number.
| Keywords: | cls, class, stellar |
| For help: | cls [help] |
| Examples: |
|


Hi all,
I'm trying to get my emonTX to take temperature readings from a DS18B20 (with the plan to add more sensors later). I have made a temperature sensor wired up to a jack plug. I tried to upload the temperature search sketch, but I couldn't get anything to come up on the serial monitor. I then realised that a wire had come loose on the temp sensor (due to some dodgy soldering!).
If I'm reading the code correctly, there still should have been something on the serial monitor, as the setup creates a couple of lines of text;
delay(1000);
Serial.begin(9600);
Serial.println("Temperature search");
Serial.println("waiting 6 seconds before printing");
delay(6000);
This should work regardless of whether the temp sensor was working or not, I am correct?
I'm using the USB to serial UART programmer from the Openenergy store. I assume this can be used for serial monitoring?
I'm a bit of a noob here so could be making a rookie error!
Thanks!
Re: Temperatures search sketch problem SOLVED
You are correct, those lines should appear.
I presume you loaded the sketch and no error messages appeared?
Have you set the baud rate of your monitor to the baud rate in the sketch - 9600 baud (the number in Serial.begin) ?
Are you using a 5 V USB supply to your emonTx?
If you are on Windows and using the Arduino IDE, you might want to increase the first delay to 6 or 7 seconds (6000 or 7000) to give yourself time to switch the monitor on. Otherwise, if you can't realise it's finished loading and switch over in under 1 second (I can't), you've missed those messages.
Re: Temperatures search sketch problem SOLVED
Robert, thanks a lot. I increase the initial delay to 7000 and it now works.
Re: Temperatures search sketch problem SOLVED
It was working all the time then, the problem was it all happened before you could see it.


{% block head %} {% endblock %}
SCEE
Home
Gallery
Upcoming
Projects
Alumni
History
Papers
StayInTouch
Our Blogs
{% block body %} {% endblock %}


RT @arrrrcamp: We've just published the first speakers to the site. We'll have the full schedule up for you fairly soon! http://t.co/G0bDj…
7/31/2015, 7:34:41 AM
Favs: 0
Retweets: 0
link--- layout: tweet ---
RT @arrrrcamp: We've just published the first speakers to the site.


Wallet Generator
Private Key:
Public Key:
Data Post
New Credit Data:
business
address
business.name
business.registered_name
business.trading_name
business.tax.code
business.tax.enrol_date
Node:
credible-1.testnet.smartpesa.com
credible-2.testnet.smartpesa.com
credible-3.testnet.smartpesa.com
Output:
Claim:
Nonce:
Sign ID:
Txn ID:
Token Balance
Wallet Token Balance:
0
PESA
Encryption
Result:
Search
Meta data:
Transaction ID List
Transaction Detail


This app is created in order to test different technologies.
In the map section, you can type a name of any place (address or cafe or whatever google maps can
find) in the text field, this app will provide you 5 hints. Results are bounded within the border of Germany. When you choose any item from the hints provided, the google map will move to the location of that place and mark it with a marker.
This app uses:
Please find my profile here.
| Title | Popularity | Release date |
|---|---|---|
| {{film.original_title}} | {{film.popularity | number:2}} | {{film.release_date | date:'dd/MM/yyyy'}} |


I'm sorry, your browser does not meet the minimum requirements to play this game.
Minimum screen size: 1280px x 600px


I want this with a banner on the bottom, then my name in the top
Here I would like to have three "buttons" one for illustrator, the center for game and app design and the last for website OR for need a drummer? type thing. I would like for them to be icons that can move in and zoom in when you hover over them. Add a store for merch! I want to make one, make some type of brand.....
for the bottom always have social media links available LIKE --> Find me on: deviantART, youtube, instagram, twitter
This website will have java and css, I want to use it as practice in order to make my website better.
For the background I want something really simple, maybe faded black or faded lines I draw on Ai or something
Things I do for fun! (In this area I want to add images of me drawing and videos of me sketching


The effect of toremifene therapy on serum immunoglobulin levels in breast cancer.
Abstract
Estrogens and anti-estrogens enhance the number of immunoglobulin (Ig) -secreting cells in pokeweed mitogen (PWM) -stimulated lymphocyte cultures. Lymphocytes from patients who have received anti-estrogen therapy show similar enhancement of Ig-secreting cells after PWM stimulation. In this study the effect of anti-estrogen (toremifene) therapy on serum immunoglobulin (IgA, IgM, IgG) levels in breast cancer patients was investigated. Serum Ig levels were followed up to two years after or during the therapy. An unexpected finding was that the Ig levels decreased during the follow-up period. This decrease was seen in patients who responded to the therapy as well as in those who did not.


One of the strengths of the Java programming language is its support for multithreading at the language level. Much of this support centers on synchronization: coordinating activities and data access among multiple threads. The mechanism that Java uses to support synchronization is the monitor. This chapter describes monitors and shows how they are used by the Java Virtual Machine. It describes how one aspect of monitors, the locking and unlocking of data, is supported in the instruction set.
A monitor supports two kinds of thread synchronization: mutual exclusion and cooperation.
Mutual exclusion, which is supported in the Java Virtual Machine via object locks, enables multiple threads to independently work on shared data without interfering with each other.
Cooperation, which is supported in the Java Virtual Machine via the wait and notify methods of class Object
, enables threads to work together towards a common goal.
A monitor is like a building that contains one special room that can be occupied by only one thread at a time. The room usually contains some data. From the time a thread enters this room to the time it leaves, it has exclusive access to any data in the room. Entering the monitor building is called "entering the monitor." Entering the special room inside the building is called "acquiring the monitor." Occupying the room is called "owning the monitor," and leaving the room is called "releasing the monitor." Leaving the entire building is called "exiting the monitor."
In addition to being associated with a bit of data, a monitor is associated with one or more bits of code called critical sections. A critical section is code that needs to be executed as one indivisible operation. In other words, one thread must be able to execute a critical section from beginning to end without another thread concurrently executing a critical section of the same monitor. A monitor enforces this one-thread-at-a-time execution of its critical sections. The only way a thread can enter a monitor is by arriving at the beginning of one of the critical sections associated with that monitor. The only way a thread can move forward and execute the critical section is by acquiring the monitor.
When a thread arrives at the beginning of a critical section, it is placed into an entry set for the associated monitor. The entry set is like the front hallway of the monitor building. If no other thread is waiting in the entry set and no other thread currently owns the monitor, the thread aquires the monitor and continues executing the critical section. When the thread finishes executing the critical section, it exits (and releases) the monitor.
If a thread arrives at the beginning of a critical section of a monitor that is already owned by another thread, the newly arrived thread must wait in the entry set. When the current owner exits the monitor, the newly arrived thread must compete with any other threads also waiting in the entry set. Only one thread will win the competition and acquire the monitor.
The first kind of synchronization listed above, mutual exclusion, refers to the mutually exclusive execution of critical sections by multiple threads. At any one time, only one thread can be executing a critical section of a particular monitor. In general, mutual exclusion is important only when multiple threads are sharing data. If two threads are not working with any common data, they usually can't interfere with each other and needn't execute in a mutually exclusive way. On a Java Virtual Machine implementation that doesn't time slice, however, a higher priority thread that is never blocked will interfere with any lower priority threads, even if none of the threads share data. The higher priority thread will monopolize the CPU at the expense of the lower priority threads. Lower priority threads will never get any CPU time. In such a case, a monitor that protects no data may be used to orchestrate these threads to ensure all threads get some CPU time. Nevertheless, in most cases a monitor protects data that is accessed through the critical section code. In cases where the data can be accessed only through the critical sections, the monitor enforces mutually exclusive access to that data.
The other kind of synchronization listed above as supported by monitors is cooperation. Whereas mutual exclusion helps keep threads from interfering with one another for sharing data, cooperation helps threads to work together towards some common goal.
Cooperation is important when one thread needs some data to be in a particular state and another thread is responsible for getting the data into that state. For example, one thread, a "read thread," may be reading data from a buffer that another thread, a "write thread," is filling. The read thread needs the buffer to be in a "not empty" state before it can read any data out of the buffer. If the read thread discovers that the buffer is empty, it must wait. The write thread is responsible for filling the buffer with data. Once the write thread has done some more writing, the read thread can do some more reading.
The form of monitor used by the Java Virtual Machine is called a "Wait and Notify" monitor. (It is also sometimes called a "Signal and Continue" monitor.) In this kind of monitor, a thread that currently owns the monitor can suspend itself inside the monitor by executing a wait command. When a thread executes a wait, it releases the monitor and enters a wait set. The thread will stay suspended in the wait set until some time after another thread executes a notify command inside the monitor. When a thread executes a notify, it continues to own the monitor until it releases the monitor of its own accord, either by executing a wait or by completing the critical section. After the notifying thread has released the monitor, the waiting thread will be resurrected and will reacquire the monitor.
The kind of monitor used in the Java Virtual Machine is sometimes called a Signal and Continue monitor because after a thread does a notify (the signal) it retains ownership of the monitor and continues executing the critical section (the continue). At some later time, the notifying thread releases the monitor and a waiting thread is resurrected. Presumably, the waiting thread suspended itself because the data protected by the monitor wasn't in a state that would allow the thread to continue doing useful work. Also, the notifying thread presumably executed the notify command after it had placed the data protected by the monitor into the state desired by the waiting thread. But because the notifying thread continued, it may have altered the state after the notify such that the waiting thread still can't do useful work. Alternatively, a third thread may have acquired the monitor after the notifying thread released it but before the waiting thread acquired it, and the third thread may have changed the state of the protected data. As a result, a notify must often be considered by waiting threads merely as a hint that the desired state may exist. Each time a waiting thread is resurrected, it may need to check the state again to determine whether it can move forward and do useful work. If it finds the data still isn't in the desired state, the thread could execute another wait or give up and exit the monitor.
As an example, consider once again the scenario described above that involves a buffer, a read thread, and a write thread. Assume the buffer is protected by a monitor. When a read thread enters the monitor that protects the buffer, it checks to see if the buffer is empty. If the buffer is not empty, the read thread reads (and removes ) some data from the buffer. Satisfied, it exits the monitor. On the other hand, if the buffer is empty, the read thread executes a wait command. As soon as it executes the wait, the read thread is suspended and placed into the monitor's wait set. In the process, the read thread releases the monitor, which becomes available to other threads. At some later time, the write thread enters the monitor, writes some data into the buffer, executes a notify, and exits the monitor. When the write thread executes the notify, the read thread is marked for eventual resurrection. After the write thread has exited the monitor, the read thread is resurrected as the owner of the monitor. If there is any chance that some other thread has come along and consumed the data left by the write thread, the read thread must explicitly check to make sure the buffer is not empty. If there is no chance that any other thread has consumed the data, then the read thread can just assume the data exists. The read thread reads some data from the buffer and exits the monitor.
A graphical depiction of the kind of monitor used by a Java Virtual Machine is shown in Figure 20-1. This figure shows the monitor as three rectangles. In the center, a large rectangle contains a single thread, the monitor's owner. On the left, a small rectangle contains the entry set. On the right, another small rectangle contains the wait set. Active threads are shown as dark gray circles. Suspended threads are shown as light gray circles.
Figure 20-1 also shows several numbered doors that threads must "pass through" to interact with the monitor. When a thread arrives at the start of a critical section, it enters the monitor via the leftmost door, door number one, and finds itself in the rectangle that houses the entry set. If no thread currently owns the monitor and no other threads are waiting in the entry set, the thread passes immediately through the next door, door number two, and becomes the owner of the monitor. As the monitor owner, the thread continues executing the critical section. If, on the other hand, there is another thread currently claiming ownership of the monitor, the newly arrived thread must wait in the entry set, possibly along with other threads already waiting there. The newly arrived thread is blocked and therefore doesn't execute any further into the critical section.
Figure 20-1 shows three threads suspended in the entry set and four threads suspended in the wait set. These threads will remain where they are until the current owner of the monitor--the active thread--releases the monitor. The active thread can release the monitor in either of two ways: it can complete the critical section it is executing or it can execute a wait command. If it completes the critical section, it exits the monitor via the door at the bottom of the central rectangle, door number five. If it executes a wait command, it releases the monitor as it travels through door number three, the door to the wait set.
If the former owner did not execute a notify before it released the monitor, then only the threads in the entry set will compete to acquire the monitor. If the former owner did execute a notify, then the entry set threads will have to compete with one or more threads from the wait set. If a thread from the entry set wins the competition, it passes through door number two and becomes the new owner of the monitor. If a thread from the wait set wins the competition, it exits the wait set and reacquires the monitor as it passes through door number four. Note that doors three and four are the only ways a thread can enter or exit the wait set. A thread can only execute a wait command if it currently owns the monitor, and it can't leave the wait set without automatically becoming again the owner of the monitor.
In the Java Virtual Machine, threads can optionally specify a timeout when they execute a wait command. If a thread does specify a timeout, and no other thread executes a notify before the timeout expires, the waiting thread in effect receives an automatic notify from the virtual machine. After the timeout expires, the waiting thread will be resurrected even if no other thread has executed an explicit notify.
The Java Virtual Machine offers two kinds of notify commands: "notify" and "notify all." A notify command selects one thread arbitrarily from the wait set and marks it for eventual resurrection. A notify all command marks all threads currently in the wait set for eventual resurrection.
To a great extent, the manner in which a Java Virtual Machine implementation selects the next thread from the wait or entry sets is a decision of individual implementation designers. For example, implementation designers can decide how to select:
You might think it would make sense to implement entry set and wait sets as first-in-first-out (FIFO) queues, so that the thread that waits the longest will be the first chosen to acquire the monitor. Alternatively, it might make sense to have ten FIFO queues, one for each priority a thread can have inside the Java Virtual Machine. The virtual machine could then choose the thread that has been waiting the longest in the highest priority queue that contains any waiting threads. Implementations may take approaches such as these, but you can't depend on it. Implementations are free to implement the entry and wait sets as last-in-first-out (LIFO) queues, to select lower priority threads before higher priority threads, or to do anything else that may not seem to make sense. Implementations are free to select threads in an arbitrary manner that defies analysis and yields surprising orderings.
As a programmer, you must not rely on any particular selection algorithm or treatment of priorities, at least if you are trying to write a Java program that is platform independent. For example, because you don't know what order threads in the wait set will be chosen for resurrection by the notify command, you should use notify (as opposed to notify all) only when you are absolutely certain there will only be one thread suspended in the wait set. If there is a chance more than one thread will be suspended in the wait set at any one time, you should probably use notify all. Otherwise, on some Java Virtual Machine implementations a particular thread may be stuck in the wait set for a very long time. If a notify always selects the most recent arrival from the wait set and the wait set always contains multiple threads, some threads that have been waiting the longest may never be resurrected.
As mentioned in earlier chapters, some of the Java Virtual Machine's runtime data areas are shared by all threads, others are private to individual threads. Because the heap and method area are shared by all threads, Java programs need to coordinate multi-threaded access to two kinds of data:
Programs never need to coordinate access to local variables, which reside on Java stacks, because data on the Java stack is private to the thread to which the Java stack belongs.
In the Java Virtual Machine, every object and class is logically associated with a monitor. For objects, the associated monitor protects the object's instance variables. For classes, the monitor protects the class's class variables. If an object has no instance variables, or a class has no class variables, the associated monitor protects no data.
To implement the mutual exclusion capability of monitors, the Java Virtual Machine associates a lock (sometimes called a mutex) with each object and class. A lock is like a privilege that only one thread can "own" at any one time. Threads need not obtain a lock to access instance or class variables. If a thread does obtain a lock, however, no other thread can access the locked data until the thread that owns the lock releases it. (To "lock an object" is to acquire the monitor associated with that object.)
Class locks are actually implemented as object locks.
As mentioned in earlier chapters, when the Java Virtual Machine loads a class file, it creates an instance of class java.lang.Class
.
When you lock a class, you are actually locking that class's Class
object.
A single thread is allowed to lock the same object multiple times. For each object, the Java Virtual Machine maintains a count of the number of times the object has been locked. An unlocked object has a count of zero. When a thread acquires the lock for the first time, the count is again incremented to one. Each time the thread acquires a lock on the same object, the count is again incremented. (Only the thread that already owns an object's lock is allowed to lock it again. No other thread can lock the object until the owning thread releases the lock.) Each time the thread releases the lock, the count is decremented. When the count reaches zero, the lock is released and made available to other threads.
A thread in the Java Virtual Machine requests a lock when it arrives at the beginning of a critical section. In Java, there are two kinds of critical sections: synchronized statements and synchronized methods. (These are described in detail later in this chapter.) Each critical section in a Java program is associated with an object reference. When a thread arrives at the first instruction in a critical section, the thread must obtain a lock on the referenced object. The thread is not allowed to execute the code until it obtains the lock. Once it has obtained the lock, the thread enters the block of protected code. When the thread leaves the block, no matter how it leaves the block, it releases the lock on the associated object.
Note that as a Java programmer, you never explicitly lock an object. Object locks are internal to the Java Virtual Machine. In your Java programs, you identify the critical sections of your program by writing synchronized statements and methods. As the Java Virtual Machine runs your program, it automatically locks an object or class every time it encounters a critical section.
As mentioned above, the language provides two built-in ways to identify critical sections in your programs: synchronized statements and synchronized methods. These two mechanisms, which implement the mutual exclusion aspect of synchronization, are supported by the Java Virtual Machine's instruction set.
To create a synchronized statement, you use the synchronized keyword with an expression that evaluates to an object reference, as in the reverseOrder()
method below:
begin // On CD-ROM in file threads/ex1/KitchenSync.java class KitchenSync { private int[] intArray = new int[10]; void reverseOrder() { synchronized (this) { int halfWay = intArray.length / 2; for (int i = 0; i < halfWay; ++i) { int upperIndex = intArray.length - 1 - i; int save = intArray[upperIndex]; intArray[upperIndex] = intArray[i]; intArray[i] = save; } } } //... } end
In the above case, the statements contained within the synchronized block will not be executed until a lock is acquired on the current object (this
).
If instead of a this
reference, the expression yielded a reference to another object, the lock associated with that object would be acquired before the thread continued.
If the expression yields a reference to an instance of class Class
, the lock associated with the class is acquired.
Two opcodes, monitorenter
and monitorexit
, are used for synchronization blocks within methods. These opcodes are shown in the Table 20-1.
| Opcode | Operand(s) | Description |
|---|---|---|
monitorenter |
none | pop objectref, acquire the lock associated with objectref |
monitorexit |
none | pop objectref, release the lock associated with objectref |
When monitorenter
is encountered by the Java Virtual Machine, it acquires the lock for the object referred to by objectref on the stack.
If the thread already owns the lock for that object, the count that is associated with the lock is incremented.
Each time monitorexit
is executed for the thread on the object, the count is decremented.
When the count reaches zero, the monitor is released.
Here is the bytecode sequence generated by the reverseOrder()
method of the KitchenSync
class:
begin // First place the reference to the object to lock into local // variable 1. This local variable will be used by both the // monitorenter and monitorexit instructions. 0 aload_0 // Push local var 0 (the this reference) 1 astore_1 // Store into local var 1 // Now acquire the lock on the referenced object // Push local var 1 (the this reference; the 2 aload_1 // object to lock) // Pop reference, acquire the lock 3 monitorenter // on referenced object // The code of the synchronized block begins here. A thread will not // execute the next instruction, aload_0, until a lock has been // successfully acquired on the this reference above. 4 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 5 getfield #4 <Field int intArray[] 8 arraylength // Pop array ref, push int array length 9 iconst_2 // Push constant int 2 10 idiv // Pop two ints, divide, push int result // Pop int into local var 3: 11 istore_3 // int halfway = intArray.length/2; // This is the start of the code for the for loop 12 iconst_0 // Push constant int 0 13 istore 4 // Pop into local var 2: int i = 0; 15 goto 65 // Jump to for loop condition check // This is the start of the body of the for loop 18 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 19 getfield #4 <Field int intArray[] 22 arraylength // Pop array ref, push int array length 23 iconst_1 // Push constant int 1 24 isub // Pop two ints, subtract, push int result 25 iload 4 // Push int at local var 4 (i) 27 isub // Pop two ints, subtract, push int result // Pop int into local var 5: 28 istore 5 // int upperindex = intArray.length - 1 - i; 30 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 31 getfield #4 <Field int intArray[] 34 iload 5 // Push int at local var 5 (upperIndex) 36 iaload // Pop index, arrayref, push int at arrayref[index] // Pop into local var 6: 37 istore 6 // int save = intArray[upperIndex]; 39 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 40 getfield #4 <Field int intArray[] 43 iload 5 // Push int at local var 5 (upperIndex) 45 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 46 getfield #4 <Field int intArray[] 49 iload 4 // Push int at local var 4 (i) 51 iaload // Pop index, arrayref, push int at arrayref[index] // Set arrayref[index] = value: 52 iastore // intArray[upperIndex] = intArray[i]; 53 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 54 getfield #4 <Field int intArray[] 57 iload 4 // Push int at local var 4 (i) 59 iload 6 // Push int at local var 6 (save) // Set arrayref[index] = value: 61 iastore // intArray[i] = save; // The body of the for loop is now done, this instruction does // the incrementing of the loop variable i 62 iinc 4 1 // Increment by 1 int at local var 4: ++i; // This is the for loop condition check: 65 iload 4 // Push int at local var 4 (i) 67 iload_3 // Push int at local var 3 (halfway) // Pop two ints, compare, jump if less than to 68 if_icmplt 18 // top of for loop body: for (; i < halfway;) // The code of the synchronized block ends here // The next two instructions unlock the object, making it available // for other threads. The reference to the locked object was stored // in local variable 1 above. 71 aload_1 // Push local var 1 (the this reference) 72 monitorexit // Pop ref, unlock object 73 return // return normally from method // This is a catch clause for any exception thrown (and not caught // from within the synchronized block. If an exception is thrown, // the locked object is unlocked, making it available for other // threads. 74 aload_1 // Push local var 1 (the this reference) 75 monitorexit // Pop ref, unlock object 76 athrow // rethrow the same exception // The exception table shows the "catch all" clause covers the // entire synchronized block, from just after the lock is acquired // to just before the lock is released. Exception table: from to target type 4 71 74 any end
Note that a catch clause ensures the locked object will be unlocked even if an exception is thrown from within the synchronized block. No matter how the synchronized block is exited, the object lock acquired when the thread entered the block will definitely be released.
To synchronize an entire method, you just include the synchronized keyword as one of the method qualifiers, as in:
begin // On CD-ROM in file threads/ex1/HeatSync.java class HeatSync { private int[] intArray = new int[10]; synchronized void reverseOrder() { int halfWay = intArray.length / 2; for (int i = 0; i < halfWay; ++i) { int upperIndex = intArray.length - 1 - i; int save = intArray[upperIndex]; intArray[upperIndex] = intArray[i]; intArray[i] = save; } } //... } end
The Java Virtual Machine does not use any special opcodes to invoke or return from synchronized methods.
When the virtual machine resolves the symbolic reference to a method, it determines whether the method is synchronized.
If so, the virtual machine acquires a lock before invoking the method.
For an instance method, the virtual machine acquires the lock associated with the object upon which the method is being invoked.
For a class method, it acquires the lock associated with the class to which the method belongs (it locks a Class
object).
After a synchronized method completes, whether it completes by returning or by throwing an exception, the virtual machine releases the lock.
Here are the bytecodes that javac
generates for HeatSync
's reverseOrder()
method:
begin 0 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 1 getfield #4 <Field int intArray[] 4 arraylength // Pop array ref, push int array length 5 iconst_2 // Push constant int 2 6 idiv // Pop two ints, divide, push int result // Pop int into local var 1: 7 istore_1 // int halfway = intArray.length/2; // This is the start of the code for the for loop 8 iconst_0 // Push int constant 0 9 istore_2 // Pop into local var 2: int i = 0; 10 goto 54 // Jump to for loop condition check // This is the start of the body of the for loop 13 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 14 getfield #4 <Field int intArray[] 17 arraylength // Pop array ref, push int array length 18 iconst_1 // Push constant int 1 19 isub // Pop two ints, subtract, push int result 20 iload_2 // Push int at local var 2 (i) 21 isub // Pop two ints, subtract, push int result // Pop int into local var 3: 22 istore_3 // int upperindex = intArray.length - 1 - i; 23 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 24 getfield #4 <Field int intArray[] 27 iload_3 // Push int at local var 3 (upperIndex) 28 iaload // Pop index, arrayref, push int at arrayref[index] // Pop into local var 4: 29 istore 4 // int save = intArray[upperIndex]; 31 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 32 getfield #4 <Field int intArray[] 35 iload_3 // Push int at local var 3 (upperIndex) 36 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 37 getfield #4 <Field int intArray[] 40 iload_2 // Push int at local var 2 (i) 41 iaload // Pop index, arrayref, push int at arrayref[index] // Pop value, index, and arrayref, // Set arrayref[index] = value: 42 iastore // intArray[upperIndex] = intArray[i]; 43 aload_0 // Push the object ref at loc var 0 (the this ref) // Pop object ref, push ref to instance variable // intArray 44 getfield #4 <Field int intArray[] 47 iload_2 // Push int at local var 2 (i) 48 iload 4 // Push int at local var 4 (save) // Pop value, index, and arrayref, // Set arrayref[index] = value: 50 iastore // intArray[i] = save; // The body of the for loop is now done, this instruction does // the incrementing of the loop variable i 51 iinc 2 1 // Increment by 1 int at local var 2: ++i; // This is the for loop condition check: 54 iload_2 // Push int at local var 2 (i) 55 iload_1 // Push int at local var 1 (halfway) // Pop two ints, compare, jump if less than to 56 if_icmplt 13 // top of for loop body: for (; i < halfway;) 59 return // return (void) from method end
If you compare these bytecodes with the ones shown earlier for KitchenSync
's reverseOrder()
method,
you will see that these bytecodes are in effect those of KitchenSync
with the support for entering and exiting the monitor removed.
Instructions at offset 0 through 56 of HeatSync
's bytecodes correspond to instructions at offset 4 through 68 of KitchenSync
's bytecodes.
Because HeatSync
's reverseOrder()
method doesn't need a local variable slot to store the reference to the locked object,
the local variable positions used by each method are different.
The function of the instructions themselves, however, match up exactly.
Another difference between the two reverseOrder()
methods is that the compiler doesn't create an exception table for HeatSync
's reverseOrder()
method.
In HeatSync
's case, an exception table isn't necessary.
When this method is invoked, the Java Virtual Machine automatically acquires the lock on the this
object.
If this method completes abruptly, just as if it completes normally, the virtual machine will release the lock on the this
object automatically.
A synchronized class (static) method operates in the same way as the synchronized instance method shown in the example above.
The one difference is that instead of acquiring a lock on this
(as there is no this
in a class method),
the thread must acquire a lock on the appropriate Class
instance.
Class Object
declares five methods that enable programmers to access the Java Virtual Machine's support for the coordination aspect of synchronization.
These methods are declared public and final, so they are inherited by all classes.
They can only be invoked from within a synchronized method or statement.
In other words, the lock associated with an object must already be acquired before any of these methods are invoked.
The methods are listed in Table 20-2.
| Method | Description |
|---|---|
void wait(); |
Enter a monitor's wait set until notified by another thread |
void wait(long timeout); |
Enter a monitor's wait set until notified by another thread or timeout milliseconds elapses |
void wait(long timeout, int nanos); |
Enter a monitor's wait set until notified by another thread or timeout milliseconds plus nanos nanoseconds elapses |
void notify(); |
Wake up one thread waiting in the monitor's wait set. (If no threads are waiting, do nothing.) |
void notifyAll(); |
Wake up all threads waiting in the monitor's wait set. (If no threads are waiting, do nothing.) |
The CD-ROM contains the source code examples from this chapter in a subdirectory of the threads
directory.
For more information about the material presented in this chapter, visit the resources page: http://www.artima.com/insidejvm/resources.