| 128 | } // namespace |
| 129 | |
| 130 | void ReadVariableOp::Compute(OpKernelContext* ctx) { |
| 131 | core::RefCountPtr<Var> variable; |
| 132 | const ResourceHandle& handle = HandleFromInput(ctx, 0); |
| 133 | const auto status = LookupResource(ctx, handle, &variable); |
| 134 | OP_REQUIRES(ctx, status.ok(), |
| 135 | errors::FailedPrecondition( |
| 136 | "Error while reading resource variable ", handle.name(), |
| 137 | " from Container: ", handle.container(), |
| 138 | ". This could mean that the variable was uninitialized. ", |
| 139 | status.ToString())); |
| 140 | |
| 141 | { |
| 142 | tf_shared_lock ml(*variable->mu()); |
| 143 | // We're acquiring a reference to the underlying buffer while |
| 144 | // holding a shared lock to guarantee ordering of reads and |
| 145 | // writes when in copy-on-write mode. |
| 146 | if (!variable->copy_on_read_mode.load()) { |
| 147 | const Tensor* t = variable->tensor(); |
| 148 | OP_REQUIRES( |
| 149 | ctx, dtype_ == t->dtype(), |
| 150 | errors::InvalidArgument( |
| 151 | "Trying to read variable with wrong dtype. Expected ", |
| 152 | DataTypeString(dtype_), " got ", DataTypeString(t->dtype()))); |
| 153 | ctx->set_output(0, *t); |
| 154 | return; |
| 155 | } |
| 156 | } |
| 157 | // Note: no need to check copy_on_read_mode again here as it only changes from |
| 158 | // false to true, never the other way around. We here do the copy under an |
| 159 | // exclusive lock to avoid racing writes. |
| 160 | mutex_lock ml(*variable->mu()); |
| 161 | const Tensor* t = variable->tensor(); |
| 162 | OP_REQUIRES_OK(ctx, CopyVariable(0, ctx, t)); |
| 163 | } |
| 164 | |
| 165 | ReadVariablesOp::ReadVariablesOp(OpKernelConstruction* c) : OpKernel(c) { |
| 166 | int n; |
nothing calls this directly
no test coverage detected